blob: 7872df3bf18e62c0e934c36ec99c51994e4b54e1 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouc83ea132010-05-09 14:46:46 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Guilherme Polo5d64c332009-04-05 02:11:19 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000088 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000207 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000208
209#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219
220#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Christian Heimese93237d2007-12-19 02:37:44 +0000265#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000270(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000283#ifdef TKINTER_PROTECT_LOADTK
284static int tk_load_failed;
285#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000286
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000287
Guido van Rossum18468821994-06-20 07:49:28 +0000288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000289Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000290{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000293}
294
Barry Warsawfa701a81997-01-16 00:15:11 +0000295
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000296
Guido van Rossum18468821994-06-20 07:49:28 +0000297/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000298
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000299static int Tkinter_busywaitinterval = 20;
300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000303
Guido van Rossum00d93061998-05-28 23:06:38 +0000304/* Millisecond sleep() for Unix platforms. */
305
306static void
Fred Drake509d79a2000-07-08 04:04:38 +0000307Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000308{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
311 t.tv_sec = milli/1000;
312 t.tv_usec = (milli%1000) * 1000;
313 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000314}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000315#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000316
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000317/* Wait up to 1s for the mainloop to come up. */
318
319static int
320WaitForMainloop(TkappObject* self)
321{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
329 }
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000334}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000335#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000336
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000337
Guido van Rossum18468821994-06-20 07:49:28 +0000338static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000339AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000340{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341 if (PyString_Check(value))
342 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000343#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000344 else if (PyUnicode_Check(value)) {
345 PyObject *v = PyUnicode_AsUTF8String(value);
346 if (v == NULL)
347 return NULL;
348 if (PyList_Append(tmp, v) != 0) {
349 Py_DECREF(v);
350 return NULL;
351 }
352 Py_DECREF(v);
353 return PyString_AsString(v);
354 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000355#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 else {
357 PyObject *v = PyObject_Str(value);
358 if (v == NULL)
359 return NULL;
360 if (PyList_Append(tmp, v) != 0) {
361 Py_DECREF(v);
362 return NULL;
363 }
364 Py_DECREF(v);
365 return PyString_AsString(v);
366 }
Guido van Rossum18468821994-06-20 07:49:28 +0000367}
368
Barry Warsawfa701a81997-01-16 00:15:11 +0000369
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000370
Guido van Rossum18468821994-06-20 07:49:28 +0000371#define ARGSZ 64
372
373static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000374Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000375{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000376 PyObject *tmp = NULL;
377 char *argvStore[ARGSZ];
378 char **argv = NULL;
379 int fvStore[ARGSZ];
380 int *fv = NULL;
381 int argc = 0, fvc = 0, i;
382 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000384 if (!(tmp = PyList_New(0)))
385 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000387 argv = argvStore;
388 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000389
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000390 if (args == NULL)
391 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000392
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000393 else if (!PyTuple_Check(args)) {
394 argc = 1;
395 fv[0] = 0;
396 if (!(argv[0] = AsString(args, tmp)))
397 goto finally;
398 }
399 else {
400 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000401
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000402 if (argc > ARGSZ) {
403 argv = (char **)ckalloc(argc * sizeof(char *));
404 fv = (int *)ckalloc(argc * sizeof(int));
405 if (argv == NULL || fv == NULL) {
406 PyErr_NoMemory();
407 goto finally;
408 }
409 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000410
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000411 for (i = 0; i < argc; i++) {
412 PyObject *v = PyTuple_GetItem(args, i);
413 if (PyTuple_Check(v)) {
414 fv[i] = 1;
415 if (!(argv[i] = Merge(v)))
416 goto finally;
417 fvc++;
418 }
419 else if (v == Py_None) {
420 argc = i;
421 break;
422 }
423 else {
424 fv[i] = 0;
425 if (!(argv[i] = AsString(v, tmp)))
426 goto finally;
427 fvc++;
428 }
429 }
430 }
431 res = Tcl_Merge(argc, argv);
432 if (res == NULL)
433 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000436 for (i = 0; i < fvc; i++)
437 if (fv[i]) {
438 ckfree(argv[i]);
439 }
440 if (argv != argvStore)
441 ckfree(FREECAST argv);
442 if (fv != fvStore)
443 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000445 Py_DECREF(tmp);
446 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000447}
448
Barry Warsawfa701a81997-01-16 00:15:11 +0000449
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000450
Guido van Rossum18468821994-06-20 07:49:28 +0000451static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000452Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 int argc;
455 char **argv;
456 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458 if (list == NULL) {
459 Py_INCREF(Py_None);
460 return Py_None;
461 }
Guido van Rossum18468821994-06-20 07:49:28 +0000462
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000463 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
464 /* Not a list.
465 * Could be a quoted string containing funnies, e.g. {"}.
466 * Return the string itself.
467 */
468 return PyString_FromString(list);
469 }
Guido van Rossum18468821994-06-20 07:49:28 +0000470
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 if (argc == 0)
472 v = PyString_FromString("");
473 else if (argc == 1)
474 v = PyString_FromString(argv[0]);
475 else if ((v = PyTuple_New(argc)) != NULL) {
476 int i;
477 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 for (i = 0; i < argc; i++) {
480 if ((w = Split(argv[i])) == NULL) {
481 Py_DECREF(v);
482 v = NULL;
483 break;
484 }
485 PyTuple_SetItem(v, i, w);
486 }
487 }
488 Tcl_Free(FREECAST argv);
489 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000490}
491
Martin v. Löwisffad6332002-11-26 09:28:05 +0000492/* In some cases, Tcl will still return strings that are supposed to be
493 lists. SplitObj walks through a nested tuple, finding string objects that
494 need to be split. */
495
Martin v. Löwis111c1802008-06-13 07:47:47 +0000496static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000497SplitObj(PyObject *arg)
498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000499 if (PyTuple_Check(arg)) {
500 int i, size;
501 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000502
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000503 size = PyTuple_Size(arg);
504 result = NULL;
505 /* Recursively invoke SplitObj for all tuple items.
506 If this does not return a new object, no action is
507 needed. */
508 for(i = 0; i < size; i++) {
509 elem = PyTuple_GetItem(arg, i);
510 newelem = SplitObj(elem);
511 if (!newelem) {
512 Py_XDECREF(result);
513 return NULL;
514 }
515 if (!result) {
516 int k;
517 if (newelem == elem) {
518 Py_DECREF(newelem);
519 continue;
520 }
521 result = PyTuple_New(size);
522 if (!result)
523 return NULL;
524 for(k = 0; k < i; k++) {
525 elem = PyTuple_GetItem(arg, k);
526 Py_INCREF(elem);
527 PyTuple_SetItem(result, k, elem);
528 }
529 }
530 PyTuple_SetItem(result, i, newelem);
531 }
532 if (result)
533 return result;
534 /* Fall through, returning arg. */
535 }
536 else if (PyString_Check(arg)) {
537 int argc;
538 char **argv;
539 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000540
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000541 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
542 Py_INCREF(arg);
543 return arg;
544 }
545 Tcl_Free(FREECAST argv);
546 if (argc > 1)
547 return Split(PyString_AsString(arg));
548 /* Fall through, returning arg. */
549 }
550 Py_INCREF(arg);
551 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000552}
Barry Warsawfa701a81997-01-16 00:15:11 +0000553
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000554
Guido van Rossum18468821994-06-20 07:49:28 +0000555/**** Tkapp Object ****/
556
557#ifndef WITH_APPINIT
558int
Fred Drake509d79a2000-07-08 04:04:38 +0000559Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000560{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000561 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000562
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000563 if (Tcl_Init(interp) == TCL_ERROR) {
564 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
565 return TCL_ERROR;
566 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000567
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000568 _tkinter_skip_tk_init = Tcl_GetVar(interp,
569 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
570 if (_tkinter_skip_tk_init != NULL &&
571 strcmp(_tkinter_skip_tk_init, "1") == 0) {
572 return TCL_OK;
573 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000574
575#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000576 if (tk_load_failed) {
577 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
578 return TCL_ERROR;
579 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000580#endif
581
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000582 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000583#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000584 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000585#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000586 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
587 return TCL_ERROR;
588 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000589
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000590 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000591}
592#endif /* !WITH_APPINIT */
593
Guido van Rossum18468821994-06-20 07:49:28 +0000594
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000595
Barry Warsawfa701a81997-01-16 00:15:11 +0000596
597/* Initialize the Tk application; see the `main' function in
598 * `tkMain.c'.
599 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000600
Thomas Wouters58d05102000-07-24 14:43:35 +0000601static void EnableEventHook(void); /* Forward */
602static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000603
Barry Warsawfa701a81997-01-16 00:15:11 +0000604static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000605Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000606 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000607{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000608 TkappObject *v;
609 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000610
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 v = PyObject_New(TkappObject, &Tkapp_Type);
612 if (v == NULL)
613 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000614
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000615 v->interp = Tcl_CreateInterp();
616 v->wantobjects = wantobjects;
617 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
618 TCL_GLOBAL_ONLY) != NULL;
619 v->thread_id = Tcl_GetCurrentThread();
620 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000621
622#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000623 if (v->threaded) {
624 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
625 Py_DECREF(v);
626 return 0;
627 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000629#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000630 if (v->threaded && tcl_lock) {
631 /* If Tcl is threaded, we don't need the lock. */
632 PyThread_free_lock(tcl_lock);
633 tcl_lock = NULL;
634 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000635#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000636
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000637 v->BooleanType = Tcl_GetObjType("boolean");
638 v->ByteArrayType = Tcl_GetObjType("bytearray");
639 v->DoubleType = Tcl_GetObjType("double");
640 v->IntType = Tcl_GetObjType("int");
641 v->ListType = Tcl_GetObjType("list");
642 v->ProcBodyType = Tcl_GetObjType("procbody");
643 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000644
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000645 /* Delete the 'exit' command, which can screw things up */
646 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000647
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000648 if (screenName != NULL)
649 Tcl_SetVar2(v->interp, "env", "DISPLAY",
650 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000652 if (interactive)
653 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
654 else
655 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000656
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000657 /* This is used to get the application class for Tk 4.1 and up */
658 argv0 = (char*)ckalloc(strlen(className) + 1);
659 if (!argv0) {
660 PyErr_NoMemory();
661 Py_DECREF(v);
662 return NULL;
663 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000664
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000665 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200666 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
667 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000668 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
669 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000670
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000671 if (! wantTk) {
672 Tcl_SetVar(v->interp,
673 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
674 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000675#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000676 else if (tk_load_failed) {
677 Tcl_SetVar(v->interp,
678 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
679 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000680#endif
David Aschere2b4b322004-02-18 05:59:53 +0000681
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000682 /* some initial arguments need to be in argv */
683 if (sync || use) {
684 char *args;
685 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 if (sync)
688 len += sizeof "-sync";
689 if (use)
690 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 args = (char*)ckalloc(len);
693 if (!args) {
694 PyErr_NoMemory();
695 Py_DECREF(v);
696 return NULL;
697 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000698
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000699 args[0] = '\0';
700 if (sync)
701 strcat(args, "-sync");
702 if (use) {
703 if (sync)
704 strcat(args, " ");
705 strcat(args, "-use ");
706 strcat(args, use);
707 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000708
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000709 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
710 ckfree(args);
711 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000712
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000713 if (Tcl_AppInit(v->interp) != TCL_OK) {
714 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000715#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000716 if (wantTk) {
717 const char *_tkinter_tk_failed;
718 _tkinter_tk_failed = Tcl_GetVar(v->interp,
719 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000720
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000721 if ( _tkinter_tk_failed != NULL &&
722 strcmp(_tkinter_tk_failed, "1") == 0) {
723 tk_load_failed = 1;
724 }
725 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000726#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000727 Py_DECREF((PyObject *)v);
728 return (TkappObject *)result;
729 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000730
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000731 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000732
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000733 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000734}
735
Barry Warsawfa701a81997-01-16 00:15:11 +0000736
Guilherme Polo1972d162009-03-27 21:43:08 +0000737#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000738static void
739Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000740 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000741{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000742 Py_BEGIN_ALLOW_THREADS;
743 Tcl_MutexLock(mutex);
744 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
745 Tcl_ThreadAlert(self->thread_id);
746 Tcl_ConditionWait(cond, mutex, NULL);
747 Tcl_MutexUnlock(mutex);
748 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000749}
Guilherme Polo1972d162009-03-27 21:43:08 +0000750#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000751
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000752
Guido van Rossum18468821994-06-20 07:49:28 +0000753/** Tcl Eval **/
754
Martin v. Löwisffad6332002-11-26 09:28:05 +0000755typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 PyObject_HEAD
757 Tcl_Obj *value;
758 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000759} PyTclObject;
760
761staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000763
764static PyObject *
765newPyTclObject(Tcl_Obj *arg)
766{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 PyTclObject *self;
768 self = PyObject_New(PyTclObject, &PyTclObject_Type);
769 if (self == NULL)
770 return NULL;
771 Tcl_IncrRefCount(arg);
772 self->value = arg;
773 self->string = NULL;
774 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000775}
776
777static void
778PyTclObject_dealloc(PyTclObject *self)
779{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000780 Tcl_DecrRefCount(self->value);
781 Py_XDECREF(self->string);
782 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000783}
784
785static PyObject *
786PyTclObject_str(PyTclObject *self)
787{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000788 if (self->string && PyString_Check(self->string)) {
789 Py_INCREF(self->string);
790 return self->string;
791 }
792 /* XXX Could cache value if it is an ASCII string. */
793 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794}
795
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000796static char*
797PyTclObject_TclString(PyObject *self)
798{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000799 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000800}
801
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000802/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000803PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000804"the string representation of this object, either as string or Unicode");
805
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000806static PyObject *
807PyTclObject_string(PyTclObject *self, void *ignored)
808{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000809 char *s;
810 int i, len;
811 if (!self->string) {
812 s = Tcl_GetStringFromObj(self->value, &len);
813 for (i = 0; i < len; i++)
814 if (s[i] & 0x80)
815 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000816#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000817 if (i == len)
818 /* It is an ASCII string. */
819 self->string = PyString_FromStringAndSize(s, len);
820 else {
821 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
822 if (!self->string) {
823 PyErr_Clear();
824 self->string = PyString_FromStringAndSize(s, len);
825 }
826 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000827#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000828 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000829#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830 if (!self->string)
831 return NULL;
832 }
833 Py_INCREF(self->string);
834 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000835}
836
837#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000838PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
839
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840static PyObject *
841PyTclObject_unicode(PyTclObject *self, void *ignored)
842{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000843 char *s;
844 int len;
845 if (self->string && PyUnicode_Check(self->string)) {
846 Py_INCREF(self->string);
847 return self->string;
848 }
849 /* XXX Could chache result if it is non-ASCII. */
850 s = Tcl_GetStringFromObj(self->value, &len);
851 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000852}
853#endif
854
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855static PyObject *
856PyTclObject_repr(PyTclObject *self)
857{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000858 char buf[50];
859 PyOS_snprintf(buf, 50, "<%s object at %p>",
860 self->value->typePtr->name, self->value);
861 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862}
863
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000864static int
865PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
866{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000867 int res;
868 res = strcmp(Tcl_GetString(self->value),
869 Tcl_GetString(other->value));
870 if (res < 0) return -1;
871 if (res > 0) return 1;
872 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000873}
874
Martin v. Löwis39195712003-01-04 00:33:13 +0000875PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
876
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877static PyObject*
878get_typename(PyTclObject* obj, void* ignored)
879{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000880 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000881}
882
Martin v. Löwis39195712003-01-04 00:33:13 +0000883
Martin v. Löwisffad6332002-11-26 09:28:05 +0000884static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000885 {"typename", (getter)get_typename, NULL, get_typename__doc__},
886 {"string", (getter)PyTclObject_string, NULL,
887 PyTclObject_string__doc__},
888 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889};
890
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000891static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000892#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000893 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
894 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000895#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000896 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000897};
898
Martin v. Löwisffad6332002-11-26 09:28:05 +0000899statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000900 PyObject_HEAD_INIT(NULL)
901 0, /*ob_size*/
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject), /*tp_basicsize*/
904 0, /*tp_itemsize*/
905 /* methods */
906 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
907 0, /*tp_print*/
908 0, /*tp_getattr*/
909 0, /*tp_setattr*/
910 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
911 (reprfunc)PyTclObject_repr, /*tp_repr*/
912 0, /*tp_as_number*/
913 0, /*tp_as_sequence*/
914 0, /*tp_as_mapping*/
915 0, /*tp_hash*/
916 0, /*tp_call*/
917 (reprfunc)PyTclObject_str, /*tp_str*/
918 PyObject_GenericGetAttr,/*tp_getattro*/
919 0, /*tp_setattro*/
920 0, /*tp_as_buffer*/
921 Py_TPFLAGS_DEFAULT, /*tp_flags*/
922 0, /*tp_doc*/
923 0, /*tp_traverse*/
924 0, /*tp_clear*/
925 0, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
927 0, /*tp_iter*/
928 0, /*tp_iternext*/
929 PyTclObject_methods, /*tp_methods*/
930 0, /*tp_members*/
931 PyTclObject_getsetlist, /*tp_getset*/
932 0, /*tp_base*/
933 0, /*tp_dict*/
934 0, /*tp_descr_get*/
935 0, /*tp_descr_set*/
936 0, /*tp_dictoffset*/
937 0, /*tp_init*/
938 0, /*tp_alloc*/
939 0, /*tp_new*/
940 0, /*tp_free*/
941 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942};
943
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000944static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000945AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000946{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000947 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000948
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000949 if (PyString_Check(value))
950 return Tcl_NewStringObj(PyString_AS_STRING(value),
951 PyString_GET_SIZE(value));
952 else if (PyBool_Check(value))
953 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
954 else if (PyInt_Check(value))
955 return Tcl_NewLongObj(PyInt_AS_LONG(value));
956 else if (PyFloat_Check(value))
957 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
958 else if (PyTuple_Check(value)) {
959 Tcl_Obj **argv = (Tcl_Obj**)
960 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
961 int i;
962 if(!argv)
963 return 0;
964 for(i=0;i<PyTuple_Size(value);i++)
965 argv[i] = AsObj(PyTuple_GetItem(value,i));
966 result = Tcl_NewListObj(PyTuple_Size(value), argv);
967 ckfree(FREECAST argv);
968 return result;
969 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000970#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000971 else if (PyUnicode_Check(value)) {
972 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
973 Py_ssize_t size = PyUnicode_GET_SIZE(value);
974 /* This #ifdef assumes that Tcl uses UCS-2.
975 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000976#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000977 Tcl_UniChar *outbuf = NULL;
978 Py_ssize_t i;
979 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
980 if (allocsize >= size)
981 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
982 /* Else overflow occurred, and we take the next exit */
983 if (!outbuf) {
984 PyErr_NoMemory();
985 return NULL;
986 }
987 for (i = 0; i < size; i++) {
988 if (inbuf[i] >= 0x10000) {
989 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +0200990 PyErr_Format(Tkinter_TclError,
991 "character U+%x is above the range "
992 "(U+0000-U+FFFF) allowed by Tcl",
993 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000994 ckfree(FREECAST outbuf);
995 return NULL;
996 }
997 outbuf[i] = inbuf[i];
998 }
999 result = Tcl_NewUnicodeObj(outbuf, size);
1000 ckfree(FREECAST outbuf);
1001 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001002#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001003 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001004#endif
1005
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001006 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001007#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001008 else if(PyTclObject_Check(value)) {
1009 Tcl_Obj *v = ((PyTclObject*)value)->value;
1010 Tcl_IncrRefCount(v);
1011 return v;
1012 }
1013 else {
1014 PyObject *v = PyObject_Str(value);
1015 if (!v)
1016 return 0;
1017 result = AsObj(v);
1018 Py_DECREF(v);
1019 return result;
1020 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001021}
1022
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023static PyObject*
1024FromObj(PyObject* tkapp, Tcl_Obj *value)
1025{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001026 PyObject *result = NULL;
1027 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001029 if (value->typePtr == NULL) {
1030 /* If the result contains any bytes with the top bit set,
1031 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001032#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001033 int i;
1034 char *s = value->bytes;
1035 int len = value->length;
1036 for (i = 0; i < len; i++) {
1037 if (value->bytes[i] & 0x80)
1038 break;
1039 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001040
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001041 if (i == value->length)
1042 result = PyString_FromStringAndSize(s, len);
1043 else {
1044 /* Convert UTF-8 to Unicode string */
1045 result = PyUnicode_DecodeUTF8(s, len, "strict");
1046 if (result == NULL) {
1047 PyErr_Clear();
1048 result = PyString_FromStringAndSize(s, len);
1049 }
1050 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001051#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001052 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001053#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001054 return result;
1055 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001057 if (value->typePtr == app->BooleanType) {
1058 result = value->internalRep.longValue ? Py_True : Py_False;
1059 Py_INCREF(result);
1060 return result;
1061 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001062
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001063 if (value->typePtr == app->ByteArrayType) {
1064 int size;
1065 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1066 return PyString_FromStringAndSize(data, size);
1067 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001068
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001069 if (value->typePtr == app->DoubleType) {
1070 return PyFloat_FromDouble(value->internalRep.doubleValue);
1071 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001072
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001073 if (value->typePtr == app->IntType) {
1074 return PyInt_FromLong(value->internalRep.longValue);
1075 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001076
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001077 if (value->typePtr == app->ListType) {
1078 int size;
1079 int i, status;
1080 PyObject *elem;
1081 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001082
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001083 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1084 if (status == TCL_ERROR)
1085 return Tkinter_Error(tkapp);
1086 result = PyTuple_New(size);
1087 if (!result)
1088 return NULL;
1089 for (i = 0; i < size; i++) {
1090 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1091 value, i, &tcl_elem);
1092 if (status == TCL_ERROR) {
1093 Py_DECREF(result);
1094 return Tkinter_Error(tkapp);
1095 }
1096 elem = FromObj(tkapp, tcl_elem);
1097 if (!elem) {
1098 Py_DECREF(result);
1099 return NULL;
1100 }
1101 PyTuple_SetItem(result, i, elem);
1102 }
1103 return result;
1104 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001105
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001106 if (value->typePtr == app->ProcBodyType) {
1107 /* fall through: return tcl object. */
1108 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001109
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001110 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001111#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001112#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001113 PyObject *result;
1114 int size;
1115 Tcl_UniChar *input;
1116 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001117
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001118 size = Tcl_GetCharLength(value);
1119 result = PyUnicode_FromUnicode(NULL, size);
1120 if (!result)
1121 return NULL;
1122 input = Tcl_GetUnicode(value);
1123 output = PyUnicode_AS_UNICODE(result);
1124 while (size--)
1125 *output++ = *input++;
1126 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001127#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001128 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1129 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001130#endif
1131#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001132 int size;
1133 char *c;
1134 c = Tcl_GetStringFromObj(value, &size);
1135 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001136#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001137 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001139 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140}
1141
Guilherme Polo1972d162009-03-27 21:43:08 +00001142#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144TCL_DECLARE_MUTEX(call_mutex)
1145
1146typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001147 Tcl_Event ev; /* Must be first */
1148 TkappObject *self;
1149 PyObject *args;
1150 int flags;
1151 PyObject **res;
1152 PyObject **exc_type, **exc_value, **exc_tb;
1153 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001155#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156
1157void
1158Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001159{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001160 int i;
1161 for (i = 0; i < objc; i++)
1162 Tcl_DecrRefCount(objv[i]);
1163 if (objv != objStore)
1164 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165}
Guido van Rossum18468821994-06-20 07:49:28 +00001166
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167/* Convert Python objects to Tcl objects. This must happen in the
1168 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001169
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170static Tcl_Obj**
1171Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1172{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001173 Tcl_Obj **objv = objStore;
1174 int objc = 0, i;
1175 if (args == NULL)
1176 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001177
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001178 else if (!PyTuple_Check(args)) {
1179 objv[0] = AsObj(args);
1180 if (objv[0] == 0)
1181 goto finally;
1182 objc = 1;
1183 Tcl_IncrRefCount(objv[0]);
1184 }
1185 else {
1186 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001187
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001188 if (objc > ARGSZ) {
1189 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1190 if (objv == NULL) {
1191 PyErr_NoMemory();
1192 objc = 0;
1193 goto finally;
1194 }
1195 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001196
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001197 for (i = 0; i < objc; i++) {
1198 PyObject *v = PyTuple_GetItem(args, i);
1199 if (v == Py_None) {
1200 objc = i;
1201 break;
1202 }
1203 objv[i] = AsObj(v);
1204 if (!objv[i]) {
1205 /* Reset objc, so it attempts to clear
1206 objects only up to i. */
1207 objc = i;
1208 goto finally;
1209 }
1210 Tcl_IncrRefCount(objv[i]);
1211 }
1212 }
1213 *pobjc = objc;
1214 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001215finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001216 Tkapp_CallDeallocArgs(objv, objStore, objc);
1217 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218}
Guido van Rossum212643f1998-04-29 16:22:14 +00001219
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001221
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222static PyObject*
1223Tkapp_CallResult(TkappObject *self)
1224{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001225 PyObject *res = NULL;
1226 if(self->wantobjects) {
1227 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1228 /* Not sure whether the IncrRef is necessary, but something
1229 may overwrite the interpreter result while we are
1230 converting it. */
1231 Tcl_IncrRefCount(value);
1232 res = FromObj((PyObject*)self, value);
1233 Tcl_DecrRefCount(value);
1234 } else {
1235 const char *s = Tcl_GetStringResult(self->interp);
1236 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001237
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001238 /* If the result contains any bytes with the top bit set,
1239 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001240#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001241 while (*p != '\0') {
1242 if (*p & 0x80)
1243 break;
1244 p++;
1245 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001246
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001247 if (*p == '\0')
1248 res = PyString_FromStringAndSize(s, (int)(p-s));
1249 else {
1250 /* Convert UTF-8 to Unicode string */
1251 p = strchr(p, '\0');
1252 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1253 if (res == NULL) {
1254 PyErr_Clear();
1255 res = PyString_FromStringAndSize(s, (int)(p-s));
1256 }
1257 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001258#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001259 p = strchr(p, '\0');
1260 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001261#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001262 }
1263 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264}
Guido van Rossum632de272000-03-29 00:19:50 +00001265
Guilherme Polo1972d162009-03-27 21:43:08 +00001266#ifdef WITH_THREAD
1267
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268/* Tkapp_CallProc is the event procedure that is executed in the context of
1269 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1270 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001271
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272static int
1273Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001275 Tcl_Obj *objStore[ARGSZ];
1276 Tcl_Obj **objv;
1277 int objc;
1278 int i;
1279 ENTER_PYTHON
1280 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1281 if (!objv) {
1282 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1283 *(e->res) = NULL;
1284 }
1285 LEAVE_PYTHON
1286 if (!objv)
1287 goto done;
1288 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1289 ENTER_PYTHON
1290 if (i == TCL_ERROR) {
1291 *(e->res) = NULL;
1292 *(e->exc_type) = NULL;
1293 *(e->exc_tb) = NULL;
1294 *(e->exc_value) = PyObject_CallFunction(
1295 Tkinter_TclError, "s",
1296 Tcl_GetStringResult(e->self->interp));
1297 }
1298 else {
1299 *(e->res) = Tkapp_CallResult(e->self);
1300 }
1301 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001302
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001303 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001304done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001305 /* Wake up calling thread. */
1306 Tcl_MutexLock(&call_mutex);
1307 Tcl_ConditionNotify(e->done);
1308 Tcl_MutexUnlock(&call_mutex);
1309 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310}
1311
Guilherme Polo1972d162009-03-27 21:43:08 +00001312#endif
1313
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314/* This is the main entry point for calling a Tcl command.
1315 It supports three cases, with regard to threading:
1316 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1317 the context of the calling thread.
1318 2. Tcl is threaded, caller of the command is in the interpreter thread:
1319 Execute the command in the calling thread. Since the Tcl lock will
1320 not be used, we can merge that with case 1.
1321 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1322 the interpreter thread. Allocation of Tcl objects needs to occur in the
1323 interpreter thread, so we ship the PyObject* args to the target thread,
1324 and perform processing there. */
1325
1326static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001327Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001329 Tcl_Obj *objStore[ARGSZ];
1330 Tcl_Obj **objv = NULL;
1331 int objc, i;
1332 PyObject *res = NULL;
1333 TkappObject *self = (TkappObject*)selfptr;
1334 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001336 /* If args is a single tuple, replace with contents of tuple */
1337 if (1 == PyTuple_Size(args)){
1338 PyObject* item = PyTuple_GetItem(args, 0);
1339 if (PyTuple_Check(item))
1340 args = item;
1341 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001342#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001343 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1344 /* We cannot call the command directly. Instead, we must
1345 marshal the parameters to the interpreter thread. */
1346 Tkapp_CallEvent *ev;
1347 Tcl_Condition cond = NULL;
1348 PyObject *exc_type, *exc_value, *exc_tb;
1349 if (!WaitForMainloop(self))
1350 return NULL;
1351 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1352 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1353 ev->self = self;
1354 ev->args = args;
1355 ev->res = &res;
1356 ev->exc_type = &exc_type;
1357 ev->exc_value = &exc_value;
1358 ev->exc_tb = &exc_tb;
1359 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001361 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001363 if (res == NULL) {
1364 if (exc_type)
1365 PyErr_Restore(exc_type, exc_value, exc_tb);
1366 else
1367 PyErr_SetObject(Tkinter_TclError, exc_value);
1368 }
1369 Tcl_ConditionFinalize(&cond);
1370 }
1371 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001372#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001373 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001375 objv = Tkapp_CallArgs(args, objStore, &objc);
1376 if (!objv)
1377 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001379 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001381 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001383 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001384
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001385 if (i == TCL_ERROR)
1386 Tkinter_Error(selfptr);
1387 else
1388 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001390 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001391
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001392 Tkapp_CallDeallocArgs(objv, objStore, objc);
1393 }
1394 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001395}
1396
1397
1398static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001399Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001400{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001401 /* Could do the same here as for Tkapp_Call(), but this is not used
1402 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1403 way for the user to do what all its Global* variants do (save and
1404 reset the scope pointer, call the local version, restore the saved
1405 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001406
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001407 char *cmd;
1408 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001409
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001410 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001411
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001412 cmd = Merge(args);
1413 if (cmd) {
1414 int err;
1415 ENTER_TCL
1416 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1417 ENTER_OVERLAP
1418 if (err == TCL_ERROR)
1419 res = Tkinter_Error(self);
1420 else
1421 res = PyString_FromString(Tkapp_Result(self));
1422 LEAVE_OVERLAP_TCL
1423 ckfree(cmd);
1424 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001425
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001426 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001427}
1428
1429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001432 char *script;
1433 PyObject *res = NULL;
1434 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001435
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001436 if (!PyArg_ParseTuple(args, "s:eval", &script))
1437 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001438
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001439 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001441 ENTER_TCL
1442 err = Tcl_Eval(Tkapp_Interp(self), script);
1443 ENTER_OVERLAP
1444 if (err == TCL_ERROR)
1445 res = Tkinter_Error(self);
1446 else
1447 res = PyString_FromString(Tkapp_Result(self));
1448 LEAVE_OVERLAP_TCL
1449 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001455 char *script;
1456 PyObject *res = NULL;
1457 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001458
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001459 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1460 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001464 ENTER_TCL
1465 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1466 ENTER_OVERLAP
1467 if (err == TCL_ERROR)
1468 res = Tkinter_Error(self);
1469 else
1470 res = PyString_FromString(Tkapp_Result(self));
1471 LEAVE_OVERLAP_TCL
1472 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001473}
1474
1475static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001476Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001477{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001478 char *fileName;
1479 PyObject *res = NULL;
1480 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001481
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1483 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001484
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001485 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001487 ENTER_TCL
1488 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1489 ENTER_OVERLAP
1490 if (err == TCL_ERROR)
1491 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001492
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001493 else
1494 res = PyString_FromString(Tkapp_Result(self));
1495 LEAVE_OVERLAP_TCL
1496 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001497}
1498
1499static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001500Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001501{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001502 char *script;
1503 PyObject *res = NULL;
1504 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001505
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001506 if (!PyArg_ParseTuple(args, "s", &script))
1507 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001509 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001511 ENTER_TCL
1512 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1513 ENTER_OVERLAP
1514 if (err == TCL_ERROR)
1515 res = Tkinter_Error(self);
1516 else
1517 res = PyString_FromString(Tkapp_Result(self));
1518 LEAVE_OVERLAP_TCL
1519 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001520}
1521
1522static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001523Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001524{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001525 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001526
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001527 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1528 return NULL;
1529 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001531 ENTER_TCL
1532 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1533 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001535 Py_INCREF(Py_None);
1536 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001537}
1538
Barry Warsawfa701a81997-01-16 00:15:11 +00001539
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001540
Guido van Rossum18468821994-06-20 07:49:28 +00001541/** Tcl Variable **/
1542
Guilherme Polo1972d162009-03-27 21:43:08 +00001543typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1544
1545#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546TCL_DECLARE_MUTEX(var_mutex)
1547
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 Tcl_Event ev; /* must be first */
1550 PyObject *self;
1551 PyObject *args;
1552 int flags;
1553 EventFunc func;
1554 PyObject **res;
1555 PyObject **exc_type;
1556 PyObject **exc_val;
1557 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001559#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001560
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001561static int
1562varname_converter(PyObject *in, void *_out)
1563{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001564 char **out = (char**)_out;
1565 if (PyString_Check(in)) {
1566 *out = PyString_AsString(in);
1567 return 1;
1568 }
1569 if (PyTclObject_Check(in)) {
1570 *out = PyTclObject_TclString(in);
1571 return 1;
1572 }
1573 /* XXX: Should give diagnostics. */
1574 return 0;
1575}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001576
Guilherme Polo1972d162009-03-27 21:43:08 +00001577#ifdef WITH_THREAD
1578
Martin v. Löwis111c1802008-06-13 07:47:47 +00001579static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001580var_perform(VarEvent *ev)
1581{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001582 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1583 if (!*(ev->res)) {
1584 PyObject *exc, *val, *tb;
1585 PyErr_Fetch(&exc, &val, &tb);
1586 PyErr_NormalizeException(&exc, &val, &tb);
1587 *(ev->exc_type) = exc;
1588 *(ev->exc_val) = val;
1589 Py_DECREF(tb);
1590 }
1591
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001592}
1593
1594static int
1595var_proc(VarEvent* ev, int flags)
1596{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001597 ENTER_PYTHON
1598 var_perform(ev);
1599 Tcl_MutexLock(&var_mutex);
1600 Tcl_ConditionNotify(ev->cond);
1601 Tcl_MutexUnlock(&var_mutex);
1602 LEAVE_PYTHON
1603 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001604}
1605
Guilherme Polo1972d162009-03-27 21:43:08 +00001606#endif
1607
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001608static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001609var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001611#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001612 TkappObject *self = (TkappObject*)selfptr;
1613 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1614 TkappObject *self = (TkappObject*)selfptr;
1615 VarEvent *ev;
1616 PyObject *res, *exc_type, *exc_val;
1617 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001618
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001619 /* The current thread is not the interpreter thread. Marshal
1620 the call to the interpreter thread, then wait for
1621 completion. */
1622 if (!WaitForMainloop(self))
1623 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001624
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001625 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1626
1627 ev->self = selfptr;
1628 ev->args = args;
1629 ev->flags = flags;
1630 ev->func = func;
1631 ev->res = &res;
1632 ev->exc_type = &exc_type;
1633 ev->exc_val = &exc_val;
1634 ev->cond = &cond;
1635 ev->ev.proc = (Tcl_EventProc*)var_proc;
1636 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1637 Tcl_ConditionFinalize(&cond);
1638 if (!res) {
1639 PyErr_SetObject(exc_type, exc_val);
1640 Py_DECREF(exc_type);
1641 Py_DECREF(exc_val);
1642 return NULL;
1643 }
1644 return res;
1645 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001646#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001647 /* Tcl is not threaded, or this is the interpreter thread. */
1648 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001649}
1650
Guido van Rossum18468821994-06-20 07:49:28 +00001651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001654 char *name1, *name2;
1655 PyObject *newValue;
1656 PyObject *res = NULL;
1657 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001658
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001659 if (PyArg_ParseTuple(args, "O&O:setvar",
1660 varname_converter, &name1, &newValue)) {
1661 /* XXX Acquire tcl lock??? */
1662 newval = AsObj(newValue);
1663 if (newval == NULL)
1664 return NULL;
1665 ENTER_TCL
1666 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1667 newval, flags);
1668 ENTER_OVERLAP
1669 if (!ok)
1670 Tkinter_Error(self);
1671 else {
1672 res = Py_None;
1673 Py_INCREF(res);
1674 }
1675 LEAVE_OVERLAP_TCL
1676 }
1677 else {
1678 PyErr_Clear();
1679 if (PyArg_ParseTuple(args, "ssO:setvar",
1680 &name1, &name2, &newValue)) {
1681 /* XXX must hold tcl lock already??? */
1682 newval = AsObj(newValue);
1683 ENTER_TCL
1684 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1685 ENTER_OVERLAP
1686 if (!ok)
1687 Tkinter_Error(self);
1688 else {
1689 res = Py_None;
1690 Py_INCREF(res);
1691 }
1692 LEAVE_OVERLAP_TCL
1693 }
1694 else {
1695 return NULL;
1696 }
1697 }
1698 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001699}
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001704 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001710 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001711}
1712
Barry Warsawfa701a81997-01-16 00:15:11 +00001713
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001714
Guido van Rossum18468821994-06-20 07:49:28 +00001715static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001716GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001717{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001718 char *name1, *name2=NULL;
1719 PyObject *res = NULL;
1720 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001721
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001722 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1723 varname_converter, &name1, &name2))
1724 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001725
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001726 ENTER_TCL
1727 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1728 ENTER_OVERLAP
1729 if (tres == NULL) {
1730 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1731 } else {
1732 if (((TkappObject*)self)->wantobjects) {
1733 res = FromObj(self, tres);
1734 }
1735 else {
1736 res = PyString_FromString(Tcl_GetString(tres));
1737 }
1738 }
1739 LEAVE_OVERLAP_TCL
1740 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001741}
1742
1743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001744Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001745{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001746 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001747}
1748
1749static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001750Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001751{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001752 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001753}
1754
Barry Warsawfa701a81997-01-16 00:15:11 +00001755
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001756
Guido van Rossum18468821994-06-20 07:49:28 +00001757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001760 char *name1, *name2=NULL;
1761 int code;
1762 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001764 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1765 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001766
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001767 ENTER_TCL
1768 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1769 ENTER_OVERLAP
1770 if (code == TCL_ERROR)
1771 res = Tkinter_Error(self);
1772 else {
1773 Py_INCREF(Py_None);
1774 res = Py_None;
1775 }
1776 LEAVE_OVERLAP_TCL
1777 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001783 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001784}
1785
1786static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001787Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001788{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001789 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001790}
1791
Barry Warsawfa701a81997-01-16 00:15:11 +00001792
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001793
Guido van Rossum18468821994-06-20 07:49:28 +00001794/** Tcl to Python **/
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001799 char *s;
1800 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001802 if (PyTuple_Size(args) == 1) {
1803 PyObject* o = PyTuple_GetItem(args, 0);
1804 if (PyInt_Check(o)) {
1805 Py_INCREF(o);
1806 return o;
1807 }
1808 }
1809 if (!PyArg_ParseTuple(args, "s:getint", &s))
1810 return NULL;
1811 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1812 return Tkinter_Error(self);
1813 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001819 char *s;
1820 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001821
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001822 if (PyTuple_Size(args) == 1) {
1823 PyObject *o = PyTuple_GetItem(args, 0);
1824 if (PyFloat_Check(o)) {
1825 Py_INCREF(o);
1826 return o;
1827 }
1828 }
1829 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1830 return NULL;
1831 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1832 return Tkinter_Error(self);
1833 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001839 char *s;
1840 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001841
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001842 if (PyTuple_Size(args) == 1) {
1843 PyObject *o = PyTuple_GetItem(args, 0);
1844 if (PyInt_Check(o)) {
1845 Py_INCREF(o);
1846 return o;
1847 }
1848 }
1849 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1850 return NULL;
1851 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1852 return Tkinter_Error(self);
1853 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001854}
1855
1856static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001857Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001858{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001859 char *s;
1860 PyObject *res = NULL;
1861 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001862
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001863 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1864 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001865
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001866 CHECK_TCL_APPARTMENT;
1867
1868 ENTER_TCL
1869 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1870 ENTER_OVERLAP
1871 if (retval == TCL_ERROR)
1872 res = Tkinter_Error(self);
1873 else
1874 res = Py_BuildValue("s", Tkapp_Result(self));
1875 LEAVE_OVERLAP_TCL
1876 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001877}
1878
1879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001882 char *s;
1883 PyObject *res = NULL;
1884 int retval;
1885 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001886
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001887 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1888 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001889
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001890 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001891
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001892 ENTER_TCL
1893 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1894 ENTER_OVERLAP
1895 if (retval == TCL_ERROR)
1896 res = Tkinter_Error(self);
1897 else
1898 res = Py_BuildValue("l", v);
1899 LEAVE_OVERLAP_TCL
1900 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001901}
1902
1903static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001904Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001905{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001906 char *s;
1907 PyObject *res = NULL;
1908 double v;
1909 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001910
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001911 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1912 return NULL;
1913 CHECK_TCL_APPARTMENT;
1914 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1915 ENTER_TCL
1916 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1917 ENTER_OVERLAP
1918 PyFPE_END_PROTECT(retval)
1919 if (retval == TCL_ERROR)
1920 res = Tkinter_Error(self);
1921 else
1922 res = Py_BuildValue("d", v);
1923 LEAVE_OVERLAP_TCL
1924 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001925}
1926
1927static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001928Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001929{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001930 char *s;
1931 PyObject *res = NULL;
1932 int retval;
1933 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001934
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001935 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1936 return NULL;
1937 CHECK_TCL_APPARTMENT;
1938 ENTER_TCL
1939 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1940 ENTER_OVERLAP
1941 if (retval == TCL_ERROR)
1942 res = Tkinter_Error(self);
1943 else
1944 res = Py_BuildValue("i", v);
1945 LEAVE_OVERLAP_TCL
1946 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001947}
1948
Barry Warsawfa701a81997-01-16 00:15:11 +00001949
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001950
Guido van Rossum18468821994-06-20 07:49:28 +00001951static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001952Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001953{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001954 char *list;
1955 int argc;
1956 char **argv;
1957 PyObject *v;
1958 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001959
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001960 if (PyTuple_Size(args) == 1) {
1961 v = PyTuple_GetItem(args, 0);
1962 if (PyTuple_Check(v)) {
1963 Py_INCREF(v);
1964 return v;
1965 }
1966 }
1967 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1968 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001969
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001970 if (Tcl_SplitList(Tkapp_Interp(self), list,
1971 &argc, &argv) == TCL_ERROR) {
1972 PyMem_Free(list);
1973 return Tkinter_Error(self);
1974 }
Guido van Rossum18468821994-06-20 07:49:28 +00001975
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001976 if (!(v = PyTuple_New(argc)))
1977 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001978
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001979 for (i = 0; i < argc; i++) {
1980 PyObject *s = PyString_FromString(argv[i]);
1981 if (!s || PyTuple_SetItem(v, i, s)) {
1982 Py_DECREF(v);
1983 v = NULL;
1984 goto finally;
1985 }
1986 }
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001989 ckfree(FREECAST argv);
1990 PyMem_Free(list);
1991 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001992}
1993
1994static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001995Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001996{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001997 PyObject *v;
1998 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001999
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002000 if (PyTuple_Size(args) == 1) {
2001 PyObject* o = PyTuple_GetItem(args, 0);
2002 if (PyTuple_Check(o)) {
2003 o = SplitObj(o);
2004 return o;
2005 }
2006 }
2007 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2008 return NULL;
2009 v = Split(list);
2010 PyMem_Free(list);
2011 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002012}
2013
2014static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002015Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002016{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002017 char *s = Merge(args);
2018 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002019
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002020 if (s) {
2021 res = PyString_FromString(s);
2022 ckfree(s);
2023 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002024
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002025 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002026}
2027
Barry Warsawfa701a81997-01-16 00:15:11 +00002028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002029
Guido van Rossum18468821994-06-20 07:49:28 +00002030/** Tcl Command **/
2031
Guido van Rossum00d93061998-05-28 23:06:38 +00002032/* Client data struct */
2033typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002034 PyObject *self;
2035 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002036} PythonCmd_ClientData;
2037
2038static int
Fred Drake509d79a2000-07-08 04:04:38 +00002039PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002040{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002041 errorInCmd = 1;
2042 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2043 LEAVE_PYTHON
2044 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002045}
2046
Guido van Rossum18468821994-06-20 07:49:28 +00002047/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002048 * function or method.
2049 */
Guido van Rossum18468821994-06-20 07:49:28 +00002050static int
Fred Drake509d79a2000-07-08 04:04:38 +00002051PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002052{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002053 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2054 PyObject *func, *arg, *res;
2055 int i, rv;
2056 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002057
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002058 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002059
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002060 /* TBD: no error checking here since we know, via the
2061 * Tkapp_CreateCommand() that the client data is a two-tuple
2062 */
2063 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002064
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002065 /* Create argument list (argv1, ..., argvN) */
2066 if (!(arg = PyTuple_New(argc - 1)))
2067 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002068
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002069 for (i = 0; i < (argc - 1); i++) {
2070 PyObject *s = PyString_FromString(argv[i + 1]);
2071 if (!s || PyTuple_SetItem(arg, i, s)) {
2072 Py_DECREF(arg);
2073 return PythonCmd_Error(interp);
2074 }
2075 }
2076 res = PyEval_CallObject(func, arg);
2077 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002078
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002079 if (res == NULL)
2080 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002082 obj_res = AsObj(res);
2083 if (obj_res == NULL) {
2084 Py_DECREF(res);
2085 return PythonCmd_Error(interp);
2086 }
2087 else {
2088 Tcl_SetObjResult(interp, obj_res);
2089 rv = TCL_OK;
2090 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002095
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002096 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002097}
2098
2099static void
Fred Drake509d79a2000-07-08 04:04:38 +00002100PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002101{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002102 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002103
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002104 ENTER_PYTHON
2105 Py_XDECREF(data->self);
2106 Py_XDECREF(data->func);
2107 PyMem_DEL(data);
2108 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002109}
2110
Barry Warsawfa701a81997-01-16 00:15:11 +00002111
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002112
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002113
Guilherme Polo1972d162009-03-27 21:43:08 +00002114#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002115TCL_DECLARE_MUTEX(command_mutex)
2116
2117typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002118 Tcl_Event ev;
2119 Tcl_Interp* interp;
2120 char *name;
2121 int create;
2122 int *status;
2123 ClientData *data;
2124 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002125} CommandEvent;
2126
2127static int
2128Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002129{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002130 if (ev->create)
2131 *ev->status = Tcl_CreateCommand(
2132 ev->interp, ev->name, PythonCmd,
2133 ev->data, PythonCmdDelete) == NULL;
2134 else
2135 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2136 Tcl_MutexLock(&command_mutex);
2137 Tcl_ConditionNotify(ev->done);
2138 Tcl_MutexUnlock(&command_mutex);
2139 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002140}
Guilherme Polo1972d162009-03-27 21:43:08 +00002141#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002142
2143static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002144Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002145{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002146 TkappObject *self = (TkappObject*)selfptr;
2147 PythonCmd_ClientData *data;
2148 char *cmdName;
2149 PyObject *func;
2150 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002151
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002152 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2153 return NULL;
2154 if (!PyCallable_Check(func)) {
2155 PyErr_SetString(PyExc_TypeError, "command not callable");
2156 return NULL;
2157 }
Guido van Rossum18468821994-06-20 07:49:28 +00002158
Martin v. Löwisa9656492003-03-30 08:44:58 +00002159#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002160 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2161 !WaitForMainloop(self))
2162 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002163#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002165 data = PyMem_NEW(PythonCmd_ClientData, 1);
2166 if (!data)
2167 return PyErr_NoMemory();
2168 Py_INCREF(self);
2169 Py_INCREF(func);
2170 data->self = selfptr;
2171 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002172
2173#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002174 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2175 Tcl_Condition cond = NULL;
2176 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2177 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2178 ev->interp = self->interp;
2179 ev->create = 1;
2180 ev->name = cmdName;
2181 ev->data = (ClientData)data;
2182 ev->status = &err;
2183 ev->done = &cond;
2184 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2185 Tcl_ConditionFinalize(&cond);
2186 }
2187 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002188#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002189 {
2190 ENTER_TCL
2191 err = Tcl_CreateCommand(
2192 Tkapp_Interp(self), cmdName, PythonCmd,
2193 (ClientData)data, PythonCmdDelete) == NULL;
2194 LEAVE_TCL
2195 }
2196 if (err) {
2197 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2198 PyMem_DEL(data);
2199 return NULL;
2200 }
Guido van Rossum18468821994-06-20 07:49:28 +00002201
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 Py_INCREF(Py_None);
2203 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002204}
2205
Barry Warsawfa701a81997-01-16 00:15:11 +00002206
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002207
Guido van Rossum18468821994-06-20 07:49:28 +00002208static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002209Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002210{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002211 TkappObject *self = (TkappObject*)selfptr;
2212 char *cmdName;
2213 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002215 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2216 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002217
2218#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002219 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2220 Tcl_Condition cond = NULL;
2221 CommandEvent *ev;
2222 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2223 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2224 ev->interp = self->interp;
2225 ev->create = 0;
2226 ev->name = cmdName;
2227 ev->status = &err;
2228 ev->done = &cond;
2229 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2230 &command_mutex);
2231 Tcl_ConditionFinalize(&cond);
2232 }
2233 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002234#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002235 {
2236 ENTER_TCL
2237 err = Tcl_DeleteCommand(self->interp, cmdName);
2238 LEAVE_TCL
2239 }
2240 if (err == -1) {
2241 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2242 return NULL;
2243 }
2244 Py_INCREF(Py_None);
2245 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002246}
2247
Barry Warsawfa701a81997-01-16 00:15:11 +00002248
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002249
Guido van Rossum00d93061998-05-28 23:06:38 +00002250#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002251/** File Handler **/
2252
Guido van Rossum00d93061998-05-28 23:06:38 +00002253typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002254 PyObject *func;
2255 PyObject *file;
2256 int id;
2257 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002258} FileHandler_ClientData;
2259
2260static FileHandler_ClientData *HeadFHCD;
2261
2262static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002263NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002264{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002265 FileHandler_ClientData *p;
2266 p = PyMem_NEW(FileHandler_ClientData, 1);
2267 if (p != NULL) {
2268 Py_XINCREF(func);
2269 Py_XINCREF(file);
2270 p->func = func;
2271 p->file = file;
2272 p->id = id;
2273 p->next = HeadFHCD;
2274 HeadFHCD = p;
2275 }
2276 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002277}
2278
2279static void
Fred Drake509d79a2000-07-08 04:04:38 +00002280DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002281{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002282 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002283
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002284 pp = &HeadFHCD;
2285 while ((p = *pp) != NULL) {
2286 if (p->id == id) {
2287 *pp = p->next;
2288 Py_XDECREF(p->func);
2289 Py_XDECREF(p->file);
2290 PyMem_DEL(p);
2291 }
2292 else
2293 pp = &p->next;
2294 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002295}
2296
Guido van Rossuma597dde1995-01-10 20:56:29 +00002297static void
Fred Drake509d79a2000-07-08 04:04:38 +00002298FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002299{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002300 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2301 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002302
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002303 ENTER_PYTHON
2304 func = data->func;
2305 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002306
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002307 arg = Py_BuildValue("(Oi)", file, (long) mask);
2308 res = PyEval_CallObject(func, arg);
2309 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002310
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002311 if (res == NULL) {
2312 errorInCmd = 1;
2313 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2314 }
2315 Py_XDECREF(res);
2316 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002317}
2318
Guido van Rossum18468821994-06-20 07:49:28 +00002319static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002320Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2321 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002322{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002323 FileHandler_ClientData *data;
2324 PyObject *file, *func;
2325 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002326
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002327 if (!self && Py_Py3kWarningFlag) {
2328 if (PyErr_Warn(PyExc_DeprecationWarning,
2329 "_tkinter.createfilehandler is gone in 3.x") < 0)
2330 return NULL;
2331 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002333 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2334 &file, &mask, &func))
2335 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002336
Martin v. Löwisa9656492003-03-30 08:44:58 +00002337#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002338 if (!self && !tcl_lock) {
2339 /* We don't have the Tcl lock since Tcl is threaded. */
2340 PyErr_SetString(PyExc_RuntimeError,
2341 "_tkinter.createfilehandler not supported "
2342 "for threaded Tcl");
2343 return NULL;
2344 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002345#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002346
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002347 if (self) {
2348 CHECK_TCL_APPARTMENT;
2349 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002350
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002351 tfile = PyObject_AsFileDescriptor(file);
2352 if (tfile < 0)
2353 return NULL;
2354 if (!PyCallable_Check(func)) {
2355 PyErr_SetString(PyExc_TypeError, "bad argument list");
2356 return NULL;
2357 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002358
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002359 data = NewFHCD(func, file, tfile);
2360 if (data == NULL)
2361 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002362
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002363 /* Ought to check for null Tcl_File object... */
2364 ENTER_TCL
2365 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2366 LEAVE_TCL
2367 Py_INCREF(Py_None);
2368 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002369}
2370
2371static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002372Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002373{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002374 PyObject *file;
2375 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002376
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002377 if (!self && Py_Py3kWarningFlag) {
2378 if (PyErr_Warn(PyExc_DeprecationWarning,
2379 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2380 return NULL;
2381 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002383 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2384 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002385
Martin v. Löwisa9656492003-03-30 08:44:58 +00002386#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002387 if (!self && !tcl_lock) {
2388 /* We don't have the Tcl lock since Tcl is threaded. */
2389 PyErr_SetString(PyExc_RuntimeError,
2390 "_tkinter.deletefilehandler not supported "
2391 "for threaded Tcl");
2392 return NULL;
2393 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002394#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002395
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002396 if (self) {
2397 CHECK_TCL_APPARTMENT;
2398 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002399
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002400 tfile = PyObject_AsFileDescriptor(file);
2401 if (tfile < 0)
2402 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002403
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002404 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002405
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002406 /* Ought to check for null Tcl_File object... */
2407 ENTER_TCL
2408 Tcl_DeleteFileHandler(tfile);
2409 LEAVE_TCL
2410 Py_INCREF(Py_None);
2411 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002412}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002413#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002414
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002415
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416/**** Tktt Object (timer token) ****/
2417
Jeremy Hylton938ace62002-07-17 16:30:39 +00002418static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002419
Guido van Rossum00d93061998-05-28 23:06:38 +00002420typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002421 PyObject_HEAD
2422 Tcl_TimerToken token;
2423 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002424} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425
2426static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002427Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002429 TkttObject *v = (TkttObject *)self;
2430 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002432 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2433 return NULL;
2434 if (v->token != NULL) {
2435 Tcl_DeleteTimerHandler(v->token);
2436 v->token = NULL;
2437 }
2438 if (func != NULL) {
2439 v->func = NULL;
2440 Py_DECREF(func);
2441 Py_DECREF(v); /* See Tktt_New() */
2442 }
2443 Py_INCREF(Py_None);
2444 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002445}
2446
2447static PyMethodDef Tktt_methods[] =
2448{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002449 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2450 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002451};
2452
2453static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002454Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002455{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002458 v = PyObject_New(TkttObject, &Tktt_Type);
2459 if (v == NULL)
2460 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002462 Py_INCREF(func);
2463 v->token = NULL;
2464 v->func = func;
2465
2466 /* Extra reference, deleted when called or when handler is deleted */
2467 Py_INCREF(v);
2468 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002469}
2470
2471static void
Fred Drake509d79a2000-07-08 04:04:38 +00002472Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002473{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002474 TkttObject *v = (TkttObject *)self;
2475 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002476
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002477 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002478
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002480}
2481
Guido van Rossum597ac201998-05-12 14:36:19 +00002482static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002483Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002484{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002485 TkttObject *v = (TkttObject *)self;
2486 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002487
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002488 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2489 v->func == NULL ? ", handler deleted" : "");
2490 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002491}
2492
2493static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002494Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002495{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002496 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002497}
2498
2499static PyTypeObject Tktt_Type =
2500{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002501 PyVarObject_HEAD_INIT(NULL, 0)
2502 "tktimertoken", /*tp_name */
2503 sizeof(TkttObject), /*tp_basicsize */
2504 0, /*tp_itemsize */
2505 Tktt_Dealloc, /*tp_dealloc */
2506 0, /*tp_print */
2507 Tktt_GetAttr, /*tp_getattr */
2508 0, /*tp_setattr */
2509 0, /*tp_compare */
2510 Tktt_Repr, /*tp_repr */
2511 0, /*tp_as_number */
2512 0, /*tp_as_sequence */
2513 0, /*tp_as_mapping */
2514 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002515};
2516
Barry Warsawfa701a81997-01-16 00:15:11 +00002517
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002518
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002519/** Timer Handler **/
2520
2521static void
Fred Drake509d79a2000-07-08 04:04:38 +00002522TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002523{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002524 TkttObject *v = (TkttObject *)clientData;
2525 PyObject *func = v->func;
2526 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002527
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002528 if (func == NULL)
2529 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002531 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002533 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002535 res = PyEval_CallObject(func, NULL);
2536 Py_DECREF(func);
2537 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002538
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002539 if (res == NULL) {
2540 errorInCmd = 1;
2541 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2542 }
2543 else
2544 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002545
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002546 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002547}
2548
2549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002550Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002551{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002552 int milliseconds;
2553 PyObject *func;
2554 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002556 if (!self && Py_Py3kWarningFlag) {
2557 if (PyErr_Warn(PyExc_DeprecationWarning,
2558 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2559 return NULL;
2560 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002561
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002562 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2563 &milliseconds, &func))
2564 return NULL;
2565 if (!PyCallable_Check(func)) {
2566 PyErr_SetString(PyExc_TypeError, "bad argument list");
2567 return NULL;
2568 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002569
Martin v. Löwisa9656492003-03-30 08:44:58 +00002570#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002571 if (!self && !tcl_lock) {
2572 /* We don't have the Tcl lock since Tcl is threaded. */
2573 PyErr_SetString(PyExc_RuntimeError,
2574 "_tkinter.createtimerhandler not supported "
2575 "for threaded Tcl");
2576 return NULL;
2577 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002578#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002579
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002580 if (self) {
2581 CHECK_TCL_APPARTMENT;
2582 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002583
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002584 v = Tktt_New(func);
2585 if (v) {
2586 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2587 (ClientData)v);
2588 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002589
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002590 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002591}
2592
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002593
Guido van Rossum18468821994-06-20 07:49:28 +00002594/** Event Loop **/
2595
Guido van Rossum18468821994-06-20 07:49:28 +00002596static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002597Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002598{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002599 int threshold = 0;
2600 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002601#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002602 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002603#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002604
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002605 if (!self && Py_Py3kWarningFlag) {
2606 if (PyErr_Warn(PyExc_DeprecationWarning,
2607 "_tkinter.mainloop is gone in 3.x") < 0)
2608 return NULL;
2609 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002610
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002611 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2612 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002613
Martin v. Löwisa9656492003-03-30 08:44:58 +00002614#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002615 if (!self && !tcl_lock) {
2616 /* We don't have the Tcl lock since Tcl is threaded. */
2617 PyErr_SetString(PyExc_RuntimeError,
2618 "_tkinter.mainloop not supported "
2619 "for threaded Tcl");
2620 return NULL;
2621 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002622#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002623
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002624 if (self) {
2625 CHECK_TCL_APPARTMENT;
2626 self->dispatching = 1;
2627 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002628
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002629 quitMainLoop = 0;
2630 while (Tk_GetNumMainWindows() > threshold &&
2631 !quitMainLoop &&
2632 !errorInCmd)
2633 {
2634 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002635
2636#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002637 if (self && self->threaded) {
2638 /* Allow other Python threads to run. */
2639 ENTER_TCL
2640 result = Tcl_DoOneEvent(0);
2641 LEAVE_TCL
2642 }
2643 else {
2644 Py_BEGIN_ALLOW_THREADS
2645 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2646 tcl_tstate = tstate;
2647 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2648 tcl_tstate = NULL;
2649 if(tcl_lock)PyThread_release_lock(tcl_lock);
2650 if (result == 0)
2651 Sleep(Tkinter_busywaitinterval);
2652 Py_END_ALLOW_THREADS
2653 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002654#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002655 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002656#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002657
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002658 if (PyErr_CheckSignals() != 0) {
2659 if (self)
2660 self->dispatching = 0;
2661 return NULL;
2662 }
2663 if (result < 0)
2664 break;
2665 }
2666 if (self)
2667 self->dispatching = 0;
2668 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002669
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002670 if (errorInCmd) {
2671 errorInCmd = 0;
2672 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2673 excInCmd = valInCmd = trbInCmd = NULL;
2674 return NULL;
2675 }
2676 Py_INCREF(Py_None);
2677 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002678}
2679
2680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002681Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002682{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002683 int flags = 0;
2684 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002685
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002686 if (!self && Py_Py3kWarningFlag) {
2687 if (PyErr_Warn(PyExc_DeprecationWarning,
2688 "_tkinter.dooneevent is gone in 3.x") < 0)
2689 return NULL;
2690 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002691
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002692 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2693 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002694
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002695 ENTER_TCL
2696 rv = Tcl_DoOneEvent(flags);
2697 LEAVE_TCL
2698 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002699}
2700
2701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002702Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002703{
2704
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002705 if (!self && Py_Py3kWarningFlag) {
2706 if (PyErr_Warn(PyExc_DeprecationWarning,
2707 "_tkinter.quit is gone in 3.x") < 0)
2708 return NULL;
2709 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002710
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002711 if (!PyArg_ParseTuple(args, ":quit"))
2712 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002713
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002714 quitMainLoop = 1;
2715 Py_INCREF(Py_None);
2716 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002717}
2718
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002719static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002720Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002721{
2722
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002723 if (!PyArg_ParseTuple(args, ":interpaddr"))
2724 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002725
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002726 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002727}
2728
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002729static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002730Tkapp_TkInit(PyObject *self, PyObject *args)
2731{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002732 Tcl_Interp *interp = Tkapp_Interp(self);
2733 const char * _tk_exists = NULL;
2734 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002735
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002736#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002737 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2738 * first call failed.
2739 * To avoid the deadlock, we just refuse the second call through
2740 * a static variable.
2741 */
2742 if (tk_load_failed) {
2743 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2744 return NULL;
2745 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002746#endif
2747
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002748 /* We want to guard against calling Tk_Init() multiple times */
2749 CHECK_TCL_APPARTMENT;
2750 ENTER_TCL
2751 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2752 ENTER_OVERLAP
2753 if (err == TCL_ERROR) {
2754 /* This sets an exception, but we cannot return right
2755 away because we need to exit the overlap first. */
2756 Tkinter_Error(self);
2757 } else {
2758 _tk_exists = Tkapp_Result(self);
2759 }
2760 LEAVE_OVERLAP_TCL
2761 if (err == TCL_ERROR) {
2762 return NULL;
2763 }
2764 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2765 if (Tk_Init(interp) == TCL_ERROR) {
2766 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002767#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002768 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002769#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002770 return NULL;
2771 }
2772 }
2773 Py_INCREF(Py_None);
2774 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002775}
Barry Warsawfa701a81997-01-16 00:15:11 +00002776
Martin v. Löwisffad6332002-11-26 09:28:05 +00002777static PyObject *
2778Tkapp_WantObjects(PyObject *self, PyObject *args)
2779{
2780
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002781 int wantobjects = -1;
2782 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2783 return NULL;
2784 if (wantobjects == -1)
2785 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2786 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002787
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002788 Py_INCREF(Py_None);
2789 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002790}
2791
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002792static PyObject *
2793Tkapp_WillDispatch(PyObject *self, PyObject *args)
2794{
2795
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002796 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002797
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002798 Py_INCREF(Py_None);
2799 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002800}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002801
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002802
Guido van Rossum18468821994-06-20 07:49:28 +00002803/**** Tkapp Method List ****/
2804
2805static PyMethodDef Tkapp_methods[] =
2806{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002807 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2808 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2809 {"call", Tkapp_Call, METH_VARARGS},
2810 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2811 {"eval", Tkapp_Eval, METH_VARARGS},
2812 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2813 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2814 {"record", Tkapp_Record, METH_VARARGS},
2815 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2816 {"setvar", Tkapp_SetVar, METH_VARARGS},
2817 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2818 {"getvar", Tkapp_GetVar, METH_VARARGS},
2819 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2820 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2821 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2822 {"getint", Tkapp_GetInt, METH_VARARGS},
2823 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2824 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2825 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2826 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2827 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2828 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2829 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2830 {"split", Tkapp_Split, METH_VARARGS},
2831 {"merge", Tkapp_Merge, METH_VARARGS},
2832 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2833 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002834#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002835 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2836 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002837#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002838 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2839 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2840 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2841 {"quit", Tkapp_Quit, METH_VARARGS},
2842 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2843 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2844 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002845};
2846
Barry Warsawfa701a81997-01-16 00:15:11 +00002847
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002848
Guido van Rossum18468821994-06-20 07:49:28 +00002849/**** Tkapp Type Methods ****/
2850
2851static void
Fred Drake509d79a2000-07-08 04:04:38 +00002852Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002853{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002854 /*CHECK_TCL_APPARTMENT;*/
2855 ENTER_TCL
2856 Tcl_DeleteInterp(Tkapp_Interp(self));
2857 LEAVE_TCL
2858 PyObject_Del(self);
2859 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002860}
2861
2862static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002863Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002864{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002865 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002866}
2867
2868static PyTypeObject Tkapp_Type =
2869{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002870 PyVarObject_HEAD_INIT(NULL, 0)
2871 "tkapp", /*tp_name */
2872 sizeof(TkappObject), /*tp_basicsize */
2873 0, /*tp_itemsize */
2874 Tkapp_Dealloc, /*tp_dealloc */
2875 0, /*tp_print */
2876 Tkapp_GetAttr, /*tp_getattr */
2877 0, /*tp_setattr */
2878 0, /*tp_compare */
2879 0, /*tp_repr */
2880 0, /*tp_as_number */
2881 0, /*tp_as_sequence */
2882 0, /*tp_as_mapping */
2883 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002884};
2885
Barry Warsawfa701a81997-01-16 00:15:11 +00002886
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002887
Guido van Rossum18468821994-06-20 07:49:28 +00002888/**** Tkinter Module ****/
2889
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002890typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002891 PyObject* tuple;
2892 int size; /* current size */
2893 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002894} FlattenContext;
2895
2896static int
2897_bump(FlattenContext* context, int size)
2898{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002899 /* expand tuple to hold (at least) size new items.
2900 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002901
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002902 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002903
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002904 if (maxsize < context->size + size)
2905 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002906
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002907 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002908
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002909 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002910}
2911
2912static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002913_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002915 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002916
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002917 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002918
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002919 if (depth > 1000) {
2920 PyErr_SetString(PyExc_ValueError,
2921 "nesting too deep in _flatten");
2922 return 0;
2923 } else if (PyList_Check(item)) {
2924 size = PyList_GET_SIZE(item);
2925 /* preallocate (assume no nesting) */
2926 if (context->size + size > context->maxsize &&
2927 !_bump(context, size))
2928 return 0;
2929 /* copy items to output tuple */
2930 for (i = 0; i < size; i++) {
2931 PyObject *o = PyList_GET_ITEM(item, i);
2932 if (PyList_Check(o) || PyTuple_Check(o)) {
2933 if (!_flatten1(context, o, depth + 1))
2934 return 0;
2935 } else if (o != Py_None) {
2936 if (context->size + 1 > context->maxsize &&
2937 !_bump(context, 1))
2938 return 0;
2939 Py_INCREF(o);
2940 PyTuple_SET_ITEM(context->tuple,
2941 context->size++, o);
2942 }
2943 }
2944 } else if (PyTuple_Check(item)) {
2945 /* same, for tuples */
2946 size = PyTuple_GET_SIZE(item);
2947 if (context->size + size > context->maxsize &&
2948 !_bump(context, size))
2949 return 0;
2950 for (i = 0; i < size; i++) {
2951 PyObject *o = PyTuple_GET_ITEM(item, i);
2952 if (PyList_Check(o) || PyTuple_Check(o)) {
2953 if (!_flatten1(context, o, depth + 1))
2954 return 0;
2955 } else if (o != Py_None) {
2956 if (context->size + 1 > context->maxsize &&
2957 !_bump(context, 1))
2958 return 0;
2959 Py_INCREF(o);
2960 PyTuple_SET_ITEM(context->tuple,
2961 context->size++, o);
2962 }
2963 }
2964 } else {
2965 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2966 return 0;
2967 }
2968 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002969}
2970
2971static PyObject *
2972Tkinter_Flatten(PyObject* self, PyObject* args)
2973{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002974 FlattenContext context;
2975 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002976
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002977 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2978 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002979
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002980 context.maxsize = PySequence_Size(item);
2981 if (context.maxsize < 0)
2982 return NULL;
2983 if (context.maxsize == 0)
2984 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002985
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002986 context.tuple = PyTuple_New(context.maxsize);
2987 if (!context.tuple)
2988 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002989
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002990 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002991
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002992 if (!_flatten1(&context, item,0))
2993 return NULL;
2994
2995 if (_PyTuple_Resize(&context.tuple, context.size))
2996 return NULL;
2997
2998 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002999}
3000
Guido van Rossum18468821994-06-20 07:49:28 +00003001static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003002Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003003{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003004 char *screenName = NULL;
3005 char *baseName = NULL;
3006 char *className = NULL;
3007 int interactive = 0;
3008 int wantobjects = 0;
3009 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3010 int sync = 0; /* pass -sync to wish */
3011 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003012
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003013 baseName = strrchr(Py_GetProgramName(), '/');
3014 if (baseName != NULL)
3015 baseName++;
3016 else
3017 baseName = Py_GetProgramName();
3018 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003019
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003020 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3021 &screenName, &baseName, &className,
3022 &interactive, &wantobjects, &wantTk,
3023 &sync, &use))
3024 return NULL;
3025
3026 return (PyObject *) Tkapp_New(screenName, baseName, className,
3027 interactive, wantobjects, wantTk,
3028 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003029}
3030
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003031static PyObject *
3032Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3033{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003034 int new_val;
3035 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3036 return NULL;
3037 if (new_val < 0) {
3038 PyErr_SetString(PyExc_ValueError,
3039 "busywaitinterval must be >= 0");
3040 return NULL;
3041 }
3042 Tkinter_busywaitinterval = new_val;
3043 Py_INCREF(Py_None);
3044 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003045}
3046
3047static char setbusywaitinterval_doc[] =
3048"setbusywaitinterval(n) -> None\n\
3049\n\
3050Set the busy-wait interval in milliseconds between successive\n\
3051calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3052It should be set to a divisor of the maximum time between\n\
3053frames in an animation.";
3054
3055static PyObject *
3056Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3057{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003058 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003059}
3060
3061static char getbusywaitinterval_doc[] =
3062"getbusywaitinterval() -> int\n\
3063\n\
3064Return the current busy-wait interval between successive\n\
3065calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3066
Guido van Rossum18468821994-06-20 07:49:28 +00003067static PyMethodDef moduleMethods[] =
3068{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003069 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3070 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003071#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003072 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3073 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003074#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003075 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3076 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3077 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3078 {"quit", Tkapp_Quit, METH_VARARGS},
3079 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3080 setbusywaitinterval_doc},
3081 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3082 METH_NOARGS, getbusywaitinterval_doc},
3083 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003084};
3085
Guido van Rossum7bf15641998-05-22 18:28:17 +00003086#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003087
3088static int stdin_ready = 0;
3089
Guido van Rossumad4db171998-06-13 13:56:28 +00003090#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003091static void
Fred Drake509d79a2000-07-08 04:04:38 +00003092MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003093{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003094 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003095}
Guido van Rossumad4db171998-06-13 13:56:28 +00003096#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003097
Martin v. Löwisa9656492003-03-30 08:44:58 +00003098#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003099static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003100#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003101
Guido van Rossum18468821994-06-20 07:49:28 +00003102static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003103EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003104{
Guido van Rossumad4db171998-06-13 13:56:28 +00003105#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003106 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003107#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003108#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003109 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003110#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003111 stdin_ready = 0;
3112 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003113#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003114 tfile = fileno(stdin);
3115 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003116#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003117 while (!errorInCmd && !stdin_ready) {
3118 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003119#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003120 if (_kbhit()) {
3121 stdin_ready = 1;
3122 break;
3123 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003124#endif
3125#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003126 Py_BEGIN_ALLOW_THREADS
3127 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3128 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003129
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003130 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003131
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003132 tcl_tstate = NULL;
3133 if(tcl_lock)PyThread_release_lock(tcl_lock);
3134 if (result == 0)
3135 Sleep(Tkinter_busywaitinterval);
3136 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003137#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003138 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003139#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003140
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003141 if (result < 0)
3142 break;
3143 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003144#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003145 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003146#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003147 if (errorInCmd) {
3148 errorInCmd = 0;
3149 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3150 excInCmd = valInCmd = trbInCmd = NULL;
3151 PyErr_Print();
3152 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003153#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003154 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003155#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003156 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003157}
Guido van Rossum18468821994-06-20 07:49:28 +00003158
Guido van Rossum00d93061998-05-28 23:06:38 +00003159#endif
3160
Guido van Rossum7bf15641998-05-22 18:28:17 +00003161static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003162EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003163{
Guido van Rossum00d93061998-05-28 23:06:38 +00003164#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003165 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003166#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003167 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003168#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003169 PyOS_InputHook = EventHook;
3170 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003171#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003172}
3173
3174static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003175DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003176{
Guido van Rossum00d93061998-05-28 23:06:38 +00003177#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003178 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3179 PyOS_InputHook = NULL;
3180 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003181#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003182}
3183
Barry Warsawfa701a81997-01-16 00:15:11 +00003184
3185/* all errors will be checked in one fell swoop in init_tkinter() */
3186static void
Fred Drake509d79a2000-07-08 04:04:38 +00003187ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003188{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003189 PyObject *v = PyInt_FromLong(val);
3190 if (v) {
3191 PyDict_SetItemString(d, name, v);
3192 Py_DECREF(v);
3193 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003194}
3195static void
Fred Drake509d79a2000-07-08 04:04:38 +00003196ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003197{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003198 PyObject *v = PyString_FromString(val);
3199 if (v) {
3200 PyDict_SetItemString(d, name, v);
3201 Py_DECREF(v);
3202 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003203}
3204
3205
Mark Hammond62b1ab12002-07-23 06:31:15 +00003206PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003207init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003208{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003209 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003210
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003211 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003212
3213#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003214 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003215#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003216
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217 m = Py_InitModule("_tkinter", moduleMethods);
3218 if (m == NULL)
3219 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003220
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003221 d = PyModule_GetDict(m);
3222 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3223 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003224
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003225 ins_long(d, "READABLE", TCL_READABLE);
3226 ins_long(d, "WRITABLE", TCL_WRITABLE);
3227 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3228 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3229 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3230 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3231 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3232 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3233 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3234 ins_string(d, "TK_VERSION", TK_VERSION);
3235 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003237 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003238
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003239 Py_TYPE(&Tktt_Type) = &PyType_Type;
3240 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003241
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003242 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3243 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003244
3245#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003246 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3247 * start waking up. Note that Tcl_FindExecutable will do this, this
3248 * code must be above it! The original warning from
3249 * tkMacOSXAppInit.c is copied below.
3250 *
3251 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3252 * Tcl interpreter for now. It probably should work to do this
3253 * in the other order, but for now it doesn't seem to.
3254 *
3255 */
3256 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003257#endif
3258
3259
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 /* This helps the dynamic loader; in Unicode aware Tcl versions
3261 it also helps Tcl find its encodings. */
3262 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 if (PyErr_Occurred())
3265 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003266
Guido van Rossum43ff8681998-07-14 18:02:13 +00003267#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003268 /* This was not a good idea; through <Destroy> bindings,
3269 Tcl_Finalize() may invoke Python code but at that point the
3270 interpreter and thread state have already been destroyed! */
3271 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003272#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003273
Guido van Rossum18468821994-06-20 07:49:28 +00003274}