blob: 29cf23315f642996c7f173742dad2eac7a8f0b88 [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
Serhiy Storchaka6716d602014-07-30 19:19:21 +030012 Only Tcl/Tk 8.4 and later are supported. Older versions are not
13 supported. Use Python 3.4 or older if you cannot upgrade your
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000014 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
Serhiy Storchaka26861b02015-02-16 20:52:17 +020024#define PY_SSIZE_T_CLEAN
Guido van Rossum35d43371997-08-02 00:09:09 +000025
Guido van Rossum9722ad81995-09-22 23:49:28 +000026#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000027#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000028
Guido van Rossum00d93061998-05-28 23:06:38 +000029#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000030#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000031#endif
32
Guido van Rossum2a5119b1998-05-29 01:28:40 +000033#ifdef MS_WINDOWS
34#include <windows.h>
35#endif
36
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030037#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka26861b02015-02-16 20:52:17 +020038 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030039
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000040/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
41 it always; if Tcl is not threaded, the thread functions in
42 Tcl are empty. */
43#define TCL_THREADS
44
Jack Jansencb852442001-12-09 23:15:56 +000045#ifdef TK_FRAMEWORK
46#include <Tcl/tcl.h>
47#include <Tk/tk.h>
48#else
Guido van Rossum18468821994-06-20 07:49:28 +000049#include <tcl.h>
50#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000051#endif
Guido van Rossum18468821994-06-20 07:49:28 +000052
Guilherme Polo2d87e422009-04-10 22:19:09 +000053#include "tkinter.h"
54
Serhiy Storchaka6716d602014-07-30 19:19:21 +030055#if TK_VERSION_HEX < 0x08040002
56#error "Tk older than 8.4 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000057#endif
58
Serhiy Storchakaea134da2015-04-02 18:46:50 +030059#if TK_VERSION_HEX >= 0x08050000
60#define HAVE_LIBTOMMAMTH
61#include <tclTomMath.h>
62#endif
63
Jack Janseneddc1442003-11-20 01:44:59 +000064#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000065#define HAVE_CREATEFILEHANDLER
66#endif
67
Guido van Rossum00d93061998-05-28 23:06:38 +000068#ifdef HAVE_CREATEFILEHANDLER
69
Neal Norwitzd948a432006-01-08 01:08:55 +000070/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
71 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
72#ifndef TCL_UNIX_FD
73# ifdef TCL_WIN_SOCKET
74# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
75# else
76# define TCL_UNIX_FD 1
77# endif
78#endif
79
Guido van Rossum00d93061998-05-28 23:06:38 +000080/* Tcl_CreateFileHandler() changed several times; these macros deal with the
81 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
82 Unix, only because Jack added it back); when available on Windows, it only
83 applies to sockets. */
84
Guido van Rossum7bf15641998-05-22 18:28:17 +000085#ifdef MS_WINDOWS
86#define FHANDLETYPE TCL_WIN_SOCKET
87#else
88#define FHANDLETYPE TCL_UNIX_FD
89#endif
90
Guido van Rossum00d93061998-05-28 23:06:38 +000091/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
92 which uses this to handle Tcl events while the user is typing commands. */
93
94#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +000095#define WAIT_FOR_STDIN
96#endif
97
Guido van Rossum00d93061998-05-28 23:06:38 +000098#endif /* HAVE_CREATEFILEHANDLER */
99
Guido van Rossumad4db171998-06-13 13:56:28 +0000100#ifdef MS_WINDOWS
101#include <conio.h>
102#define WAIT_FOR_STDIN
103#endif
104
Guido van Rossum00d93061998-05-28 23:06:38 +0000105#ifdef WITH_THREAD
106
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000107/* The threading situation is complicated. Tcl is not thread-safe, except
108 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000109
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300110 So we need to use a lock around all uses of Tcl. Previously, the
111 Python interpreter lock was used for this. However, this causes
112 problems when other Python threads need to run while Tcl is blocked
113 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000114
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300115 To solve this problem, a separate lock for Tcl is introduced.
116 Holding it is incompatible with holding Python's interpreter lock.
117 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000118
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300119 ENTER_TCL and LEAVE_TCL are brackets, just like
120 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
121 used whenever a call into Tcl is made that could call an event
122 handler, or otherwise affect the state of a Tcl interpreter. These
123 assume that the surrounding code has the Python interpreter lock;
124 inside the brackets, the Python interpreter lock has been released
125 and the lock for Tcl has been acquired.
126
127 Sometimes, it is necessary to have both the Python lock and the Tcl
128 lock. (For example, when transferring data from the Tcl
129 interpreter result to a Python string object.) This can be done by
130 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
131 reacquires the Python lock (and restores the thread state) but
132 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
133 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000134
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000135 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300136 handlers when the handler needs to use Python. Such event handlers
137 are entered while the lock for Tcl is held; the event handler
138 presumably needs to use Python. ENTER_PYTHON releases the lock for
139 Tcl and acquires the Python interpreter lock, restoring the
140 appropriate thread state, and LEAVE_PYTHON releases the Python
141 interpreter lock and re-acquires the lock for Tcl. It is okay for
142 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
143 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000144
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300145 These locks expand to several statements and brackets; they should
146 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000147
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300148 If Tcl is threaded, this approach won't work anymore. The Tcl
149 interpreter is only valid in the thread that created it, and all Tk
150 activity must happen in this thread, also. That means that the
151 mainloop must be invoked in the thread that created the
152 interpreter. Invoking commands from other threads is possible;
153 _tkinter will queue an event for the interpreter thread, which will
154 then execute the command and pass back the result. If the main
155 thread is not in the mainloop, and invoking commands causes an
156 exception; if the main loop is running but not processing events,
157 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000158
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300159 In addition, for a threaded Tcl, a single global tcl_tstate won't
160 be sufficient anymore, since multiple Tcl interpreters may
161 simultaneously dispatch in different threads. So we use the Tcl TLS
162 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000163
Guido van Rossum00d93061998-05-28 23:06:38 +0000164*/
165
Guido van Rossum65d5b571998-12-21 19:32:43 +0000166static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167
168#ifdef TCL_THREADS
169static Tcl_ThreadDataKey state_key;
170typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300171#define tcl_tstate \
172 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000173#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000174static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000175#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000176
177#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
179 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000180
181#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300182 tcl_tstate = NULL; \
183 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000184
Guido van Rossum62320c91998-06-15 04:36:09 +0000185#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000187
188#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000189 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000190
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000191#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300193 if(tcl_lock) \
194 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000195
196#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 { PyThreadState *tstate = PyEval_SaveThread(); \
198 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000199
200#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 if (((TkappObject *)self)->threaded && \
202 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300203 PyErr_SetString(PyExc_RuntimeError, \
204 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 return 0; \
206 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000207
208#else
209
210#define ENTER_TCL
211#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000212#define ENTER_OVERLAP
213#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000214#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000215#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000216#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000217
218#endif
219
Guido van Rossum97867b21996-08-08 19:09:53 +0000220#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000221#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000222#endif
223
Guido van Rossum18468821994-06-20 07:49:28 +0000224/**** Tkapp Object Declaration ****/
225
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300226static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000227
Guido van Rossum00d93061998-05-28 23:06:38 +0000228typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 PyObject_HEAD
230 Tcl_Interp *interp;
231 int wantobjects;
232 int threaded; /* True if tcl_platform[threaded] */
233 Tcl_ThreadId thread_id;
234 int dispatching;
235 /* We cannot include tclInt.h, as this is internal.
236 So we cache interesting types here. */
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200237 const Tcl_ObjType *OldBooleanType;
Zachary Ware037605b2014-08-05 11:54:34 -0500238 const Tcl_ObjType *BooleanType;
239 const Tcl_ObjType *ByteArrayType;
240 const Tcl_ObjType *DoubleType;
241 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300242 const Tcl_ObjType *WideIntType;
243 const Tcl_ObjType *BignumType;
Zachary Ware037605b2014-08-05 11:54:34 -0500244 const Tcl_ObjType *ListType;
245 const Tcl_ObjType *ProcBodyType;
246 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000247} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000248
Guido van Rossum18468821994-06-20 07:49:28 +0000249#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000250#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000251
Guido van Rossum35d43371997-08-02 00:09:09 +0000252#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000253(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000254
Barry Warsawfa701a81997-01-16 00:15:11 +0000255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256
Guido van Rossum18468821994-06-20 07:49:28 +0000257/**** Error Handling ****/
258
259static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000260static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000261static int errorInCmd = 0;
262static PyObject *excInCmd;
263static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000264static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000265
Guilherme Polob681df42009-02-09 22:33:59 +0000266#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000267static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000268#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270
Guido van Rossum18468821994-06-20 07:49:28 +0000271static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000272Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000273{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
275 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000276}
277
Barry Warsawfa701a81997-01-16 00:15:11 +0000278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279
Guido van Rossum18468821994-06-20 07:49:28 +0000280/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000281
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000282static int Tkinter_busywaitinterval = 20;
283
Guido van Rossum00d93061998-05-28 23:06:38 +0000284#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000285#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000286
Guido van Rossum00d93061998-05-28 23:06:38 +0000287/* Millisecond sleep() for Unix platforms. */
288
289static void
Fred Drake509d79a2000-07-08 04:04:38 +0000290Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000291{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 /* XXX Too bad if you don't have select(). */
293 struct timeval t;
294 t.tv_sec = milli/1000;
295 t.tv_usec = (milli%1000) * 1000;
296 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000297}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000298#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000299
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000300/* Wait up to 1s for the mainloop to come up. */
301
302static int
303WaitForMainloop(TkappObject* self)
304{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 int i;
306 for (i = 0; i < 10; i++) {
307 if (self->dispatching)
308 return 1;
309 Py_BEGIN_ALLOW_THREADS
310 Sleep(100);
311 Py_END_ALLOW_THREADS
312 }
313 if (self->dispatching)
314 return 1;
315 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
316 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000317}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000318#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321
Guido van Rossum18468821994-06-20 07:49:28 +0000322#define ARGSZ 64
323
Barry Warsawfa701a81997-01-16 00:15:11 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Guido van Rossum18468821994-06-20 07:49:28 +0000326static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200327unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
328{
329 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
330 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
331 /* Tcl encodes null character as \xc0\x80 */
332 if (memchr(s, '\xc0', size)) {
333 char *buf, *q;
334 const char *e = s + size;
335 PyErr_Clear();
336 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300337 if (buf == NULL) {
338 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200339 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300340 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200341 while (s != e) {
342 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
343 *q++ = '\0';
344 s += 2;
345 }
346 else
347 *q++ = *s++;
348 }
349 s = buf;
350 size = q - s;
351 r = PyUnicode_DecodeUTF8(s, size, NULL);
352 PyMem_Free(buf);
353 }
354 }
355 return r;
356}
357
358static PyObject *
359unicodeFromTclString(const char *s)
360{
361 return unicodeFromTclStringAndSize(s, strlen(s));
362}
363
364static PyObject *
365unicodeFromTclObj(Tcl_Obj *value)
366{
367 int len;
368 char *s = Tcl_GetStringFromObj(value, &len);
369 return unicodeFromTclStringAndSize(s, len);
370}
371
372
373static PyObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300374Split(const char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000375{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300377 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300381 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 }
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
385 /* Not a list.
386 * Could be a quoted string containing funnies, e.g. {"}.
387 * Return the string itself.
388 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200389 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 }
Guido van Rossum18468821994-06-20 07:49:28 +0000391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000392 if (argc == 0)
393 v = PyUnicode_FromString("");
394 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200395 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 else if ((v = PyTuple_New(argc)) != NULL) {
397 int i;
398 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 for (i = 0; i < argc; i++) {
401 if ((w = Split(argv[i])) == NULL) {
402 Py_DECREF(v);
403 v = NULL;
404 break;
405 }
406 PyTuple_SetItem(v, i, w);
407 }
408 }
409 Tcl_Free(FREECAST argv);
410 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000411}
412
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300413/* In some cases, Tcl will still return strings that are supposed to
414 be lists. SplitObj walks through a nested tuple, finding string
415 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000416
Martin v. Löwis59683e82008-06-13 07:50:45 +0000417static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000418SplitObj(PyObject *arg)
419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 if (PyTuple_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200421 Py_ssize_t i, size;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 size = PyTuple_Size(arg);
425 result = NULL;
426 /* Recursively invoke SplitObj for all tuple items.
427 If this does not return a new object, no action is
428 needed. */
429 for(i = 0; i < size; i++) {
430 elem = PyTuple_GetItem(arg, i);
431 newelem = SplitObj(elem);
432 if (!newelem) {
433 Py_XDECREF(result);
434 return NULL;
435 }
436 if (!result) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200437 Py_ssize_t k;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 if (newelem == elem) {
439 Py_DECREF(newelem);
440 continue;
441 }
442 result = PyTuple_New(size);
443 if (!result)
444 return NULL;
445 for(k = 0; k < i; k++) {
446 elem = PyTuple_GetItem(arg, k);
447 Py_INCREF(elem);
448 PyTuple_SetItem(result, k, elem);
449 }
450 }
451 PyTuple_SetItem(result, i, newelem);
452 }
453 if (result)
454 return result;
455 /* Fall through, returning arg. */
456 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300457 else if (PyList_Check(arg)) {
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200458 Py_ssize_t i, size;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300459 PyObject *elem, *newelem, *result;
460
461 size = PyList_GET_SIZE(arg);
462 result = PyTuple_New(size);
463 if (!result)
464 return NULL;
465 /* Recursively invoke SplitObj for all list items. */
466 for(i = 0; i < size; i++) {
467 elem = PyList_GET_ITEM(arg, i);
468 newelem = SplitObj(elem);
469 if (!newelem) {
470 Py_XDECREF(result);
471 return NULL;
472 }
473 PyTuple_SetItem(result, i, newelem);
474 }
475 return result;
476 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300477 else if (PyUnicode_Check(arg)) {
478 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300479 const char **argv;
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300480 char *list = PyUnicode_AsUTF8(arg);
481
482 if (list == NULL ||
483 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
484 Py_INCREF(arg);
485 return arg;
486 }
487 Tcl_Free(FREECAST argv);
488 if (argc > 1)
489 return Split(list);
490 /* Fall through, returning arg. */
491 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 else if (PyBytes_Check(arg)) {
493 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300494 const char **argv;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000496
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
498 Py_INCREF(arg);
499 return arg;
500 }
501 Tcl_Free(FREECAST argv);
502 if (argc > 1)
503 return Split(PyBytes_AsString(arg));
504 /* Fall through, returning arg. */
505 }
506 Py_INCREF(arg);
507 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000508}
Barry Warsawfa701a81997-01-16 00:15:11 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510
Guido van Rossum18468821994-06-20 07:49:28 +0000511/**** Tkapp Object ****/
512
513#ifndef WITH_APPINIT
514int
Fred Drake509d79a2000-07-08 04:04:38 +0000515Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000516{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000519 if (Tcl_Init(interp) == TCL_ERROR) {
520 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
521 return TCL_ERROR;
522 }
Guilherme Polob681df42009-02-09 22:33:59 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 _tkinter_skip_tk_init = Tcl_GetVar(interp,
525 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
526 if (_tkinter_skip_tk_init != NULL &&
527 strcmp(_tkinter_skip_tk_init, "1") == 0) {
528 return TCL_OK;
529 }
Guilherme Polob681df42009-02-09 22:33:59 +0000530
531#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 if (tk_load_failed) {
533 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
534 return TCL_ERROR;
535 }
Guilherme Polob681df42009-02-09 22:33:59 +0000536#endif
537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000539#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000541#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
543 return TCL_ERROR;
544 }
Guilherme Polob681df42009-02-09 22:33:59 +0000545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000547}
548#endif /* !WITH_APPINIT */
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551
Barry Warsawfa701a81997-01-16 00:15:11 +0000552
553/* Initialize the Tk application; see the `main' function in
554 * `tkMain.c'.
555 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000556
Thomas Wouters58d05102000-07-24 14:43:35 +0000557static void EnableEventHook(void); /* Forward */
558static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000559
Barry Warsawfa701a81997-01-16 00:15:11 +0000560static TkappObject *
Serhiy Storchaka6716d602014-07-30 19:19:21 +0300561Tkapp_New(const char *screenName, const char *className,
562 int interactive, int wantobjects, int wantTk, int sync,
563 const char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000564{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 TkappObject *v;
566 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000567
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300568 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 if (v == NULL)
570 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200571 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 v->interp = Tcl_CreateInterp();
574 v->wantobjects = wantobjects;
575 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
576 TCL_GLOBAL_ONLY) != NULL;
577 v->thread_id = Tcl_GetCurrentThread();
578 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000579
580#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300582 PyErr_SetString(PyExc_RuntimeError,
583 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 Py_DECREF(v);
585 return 0;
586 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000587#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000588#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 if (v->threaded && tcl_lock) {
590 /* If Tcl is threaded, we don't need the lock. */
591 PyThread_free_lock(tcl_lock);
592 tcl_lock = NULL;
593 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000594#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000595
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +0200596 v->OldBooleanType = Tcl_GetObjType("boolean");
597 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 v->ByteArrayType = Tcl_GetObjType("bytearray");
599 v->DoubleType = Tcl_GetObjType("double");
600 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300601 v->WideIntType = Tcl_GetObjType("wideInt");
602 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 v->ListType = Tcl_GetObjType("list");
604 v->ProcBodyType = Tcl_GetObjType("procbody");
605 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 /* Delete the 'exit' command, which can screw things up */
608 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 if (screenName != NULL)
611 Tcl_SetVar2(v->interp, "env", "DISPLAY",
612 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 if (interactive)
615 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
616 else
617 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 /* This is used to get the application class for Tk 4.1 and up */
Victor Stinneree6c3c72014-09-11 17:50:21 +0200620 argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 if (!argv0) {
622 PyErr_NoMemory();
623 Py_DECREF(v);
624 return NULL;
625 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200628 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
629 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200631 PyMem_Free(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 if (! wantTk) {
634 Tcl_SetVar(v->interp,
635 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
636 }
Guilherme Polob681df42009-02-09 22:33:59 +0000637#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 else if (tk_load_failed) {
639 Tcl_SetVar(v->interp,
640 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
641 }
Guilherme Polob681df42009-02-09 22:33:59 +0000642#endif
David Aschere2b4b322004-02-18 05:59:53 +0000643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 /* some initial arguments need to be in argv */
645 if (sync || use) {
646 char *args;
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200647 Py_ssize_t len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000648
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 if (sync)
650 len += sizeof "-sync";
651 if (use)
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200652 len += strlen(use) + sizeof "-use "; /* never overflows */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653
Victor Stinneree6c3c72014-09-11 17:50:21 +0200654 args = (char*)PyMem_Malloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 if (!args) {
656 PyErr_NoMemory();
657 Py_DECREF(v);
658 return NULL;
659 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 args[0] = '\0';
662 if (sync)
663 strcat(args, "-sync");
664 if (use) {
665 if (sync)
666 strcat(args, " ");
667 strcat(args, "-use ");
668 strcat(args, use);
669 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
Victor Stinneree6c3c72014-09-11 17:50:21 +0200672 PyMem_Free(args);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 if (Tcl_AppInit(v->interp) != TCL_OK) {
676 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000677#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 if (wantTk) {
679 const char *_tkinter_tk_failed;
680 _tkinter_tk_failed = Tcl_GetVar(v->interp,
681 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 if ( _tkinter_tk_failed != NULL &&
684 strcmp(_tkinter_tk_failed, "1") == 0) {
685 tk_load_failed = 1;
686 }
687 }
Guilherme Polob681df42009-02-09 22:33:59 +0000688#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
691 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Benjamin Peterson5879d412009-03-30 14:51:56 +0000699#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000700static void
701Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000703{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 Py_BEGIN_ALLOW_THREADS;
705 Tcl_MutexLock(mutex);
706 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
707 Tcl_ThreadAlert(self->thread_id);
708 Tcl_ConditionWait(cond, mutex, NULL);
709 Tcl_MutexUnlock(mutex);
710 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000711}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000712#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000713
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714
Guido van Rossum18468821994-06-20 07:49:28 +0000715/** Tcl Eval **/
716
Martin v. Löwisffad6332002-11-26 09:28:05 +0000717typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 PyObject_HEAD
719 Tcl_Obj *value;
720 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000721} PyTclObject;
722
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300723static PyObject *PyTclObject_Type;
724#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000725
726static PyObject *
727newPyTclObject(Tcl_Obj *arg)
728{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300730 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 if (self == NULL)
732 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200733 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 Tcl_IncrRefCount(arg);
735 self->value = arg;
736 self->string = NULL;
737 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000738}
739
740static void
741PyTclObject_dealloc(PyTclObject *self)
742{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200743 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 Tcl_DecrRefCount(self->value);
745 Py_XDECREF(self->string);
746 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200747 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000748}
749
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000750static char*
751PyTclObject_TclString(PyObject *self)
752{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000754}
755
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000756/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000757PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000758"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000759
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000760static PyObject *
761PyTclObject_string(PyTclObject *self, void *ignored)
762{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200764 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 if (!self->string)
766 return NULL;
767 }
768 Py_INCREF(self->string);
769 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000770}
771
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000772static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000773PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000774{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200775 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 Py_INCREF(self->string);
777 return self->string;
778 }
779 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200780 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000781}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000782
Martin v. Löwisffad6332002-11-26 09:28:05 +0000783static PyObject *
784PyTclObject_repr(PyTclObject *self)
785{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300786 PyObject *repr, *str = PyTclObject_str(self, NULL);
787 if (str == NULL)
788 return NULL;
789 repr = PyUnicode_FromFormat("<%s object: %R>",
790 self->value->typePtr->name, str);
791 Py_DECREF(str);
792 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000793}
794
Mark Dickinson211c6252009-02-01 10:28:51 +0000795#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
796
797static PyObject *
798PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000799{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 int result;
801 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 /* neither argument should be NULL, unless something's gone wrong */
804 if (self == NULL || other == NULL) {
805 PyErr_BadInternalCall();
806 return NULL;
807 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 /* both arguments should be instances of PyTclObject */
810 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
811 v = Py_NotImplemented;
812 goto finished;
813 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 if (self == other)
816 /* fast path when self and other are identical */
817 result = 0;
818 else
819 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
820 Tcl_GetString(((PyTclObject *)other)->value));
821 /* Convert return value to a Boolean */
822 switch (op) {
823 case Py_EQ:
824 v = TEST_COND(result == 0);
825 break;
826 case Py_NE:
827 v = TEST_COND(result != 0);
828 break;
829 case Py_LE:
830 v = TEST_COND(result <= 0);
831 break;
832 case Py_GE:
833 v = TEST_COND(result >= 0);
834 break;
835 case Py_LT:
836 v = TEST_COND(result < 0);
837 break;
838 case Py_GT:
839 v = TEST_COND(result > 0);
840 break;
841 default:
842 PyErr_BadArgument();
843 return NULL;
844 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000845 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 Py_INCREF(v);
847 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000848}
849
Martin v. Löwis39195712003-01-04 00:33:13 +0000850PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
851
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852static PyObject*
853get_typename(PyTclObject* obj, void* ignored)
854{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200855 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000856}
857
Martin v. Löwis39195712003-01-04 00:33:13 +0000858
Martin v. Löwisffad6332002-11-26 09:28:05 +0000859static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000860 {"typename", (getter)get_typename, NULL, get_typename__doc__},
861 {"string", (getter)PyTclObject_string, NULL,
862 PyTclObject_string__doc__},
863 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000864};
865
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300866static PyType_Slot PyTclObject_Type_slots[] = {
867 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
868 {Py_tp_repr, (reprfunc)PyTclObject_repr},
869 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200870 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300871 {Py_tp_richcompare, PyTclObject_richcompare},
872 {Py_tp_getset, PyTclObject_getsetlist},
873 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874};
875
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300876static PyType_Spec PyTclObject_Type_spec = {
877 "_tkinter.Tcl_Obj",
878 sizeof(PyTclObject),
879 0,
880 Py_TPFLAGS_DEFAULT,
881 PyTclObject_Type_slots,
882};
883
884
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300885#if PY_SIZE_MAX > INT_MAX
886#define CHECK_STRING_LENGTH(s) do { \
887 if (s != NULL && strlen(s) >= INT_MAX) { \
888 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
889 return NULL; \
890 } } while(0)
891#else
892#define CHECK_STRING_LENGTH(s)
893#endif
894
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300895#ifdef HAVE_LIBTOMMAMTH
896static Tcl_Obj*
897asBignumObj(PyObject *value)
898{
899 Tcl_Obj *result;
900 int neg;
901 PyObject *hexstr;
902 char *hexchars;
903 mp_int bigValue;
904
905 neg = Py_SIZE(value) < 0;
906 hexstr = _PyLong_Format(value, 16);
907 if (hexstr == NULL)
908 return NULL;
909 hexchars = PyUnicode_AsUTF8(hexstr);
910 if (hexchars == NULL) {
911 Py_DECREF(hexstr);
912 return NULL;
913 }
914 hexchars += neg + 2; /* skip sign and "0x" */
915 mp_init(&bigValue);
916 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
917 mp_clear(&bigValue);
918 Py_DECREF(hexstr);
919 PyErr_NoMemory();
920 return NULL;
921 }
922 Py_DECREF(hexstr);
923 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
924 result = Tcl_NewBignumObj(&bigValue);
925 mp_clear(&bigValue);
926 if (result == NULL) {
927 PyErr_NoMemory();
928 return NULL;
929 }
930 return result;
931}
932#endif
933
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000934static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000935AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000936{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000938
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200939 if (PyBytes_Check(value)) {
940 if (PyBytes_GET_SIZE(value) >= INT_MAX) {
941 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
942 return NULL;
943 }
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300944 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
Serhiy Storchaka26861b02015-02-16 20:52:17 +0200945 (int)PyBytes_GET_SIZE(value));
946 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300947
948 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300950
951 if (PyLong_CheckExact(value)) {
952 int overflow;
953 long longValue;
954#ifdef TCL_WIDE_INT_TYPE
955 Tcl_WideInt wideValue;
956#endif
957 longValue = PyLong_AsLongAndOverflow(value, &overflow);
958 if (!overflow) {
959 return Tcl_NewLongObj(longValue);
960 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300962 fall through to wideInt handling. */
963#ifdef TCL_WIDE_INT_TYPE
964 if (_PyLong_AsByteArray((PyLongObject *)value,
965 (unsigned char *)(void *)&wideValue,
966 sizeof(wideValue),
967 PY_LITTLE_ENDIAN,
968 /* signed */ 1) == 0) {
969 return Tcl_NewWideIntObj(wideValue);
970 }
971 PyErr_Clear();
972#endif
973 /* If there is an overflow in the wideInt conversion,
974 fall through to bignum handling. */
975#ifdef HAVE_LIBTOMMAMTH
976 return asBignumObj(value);
977#endif
978 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300981
982 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000983 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300984
Serhiy Storchaka4c7dc482015-04-02 18:49:14 +0300985 if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300986 Tcl_Obj **argv;
987 Py_ssize_t size, i;
988
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300989 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300990 if (size == 0)
991 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300992 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300993 PyErr_SetString(PyExc_OverflowError,
994 PyTuple_Check(value) ? "tuple is too long" :
995 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300996 return NULL;
997 }
Victor Stinneree6c3c72014-09-11 17:50:21 +0200998 argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
999 if (!argv) {
Victor Stinner60a64d62014-09-04 17:29:52 +02001000 PyErr_NoMemory();
1001 return NULL;
1002 }
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001003 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001004 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001005 result = Tcl_NewListObj((int)size, argv);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001006 PyMem_Free(argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 return result;
1008 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001009
1010 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001011 void *inbuf;
1012 Py_ssize_t size;
1013 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 Tcl_UniChar *outbuf = NULL;
1015 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001016 size_t allocsize;
1017
1018 if (PyUnicode_READY(value) == -1)
1019 return NULL;
1020
1021 inbuf = PyUnicode_DATA(value);
1022 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001023 if (size == 0)
1024 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001025 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1026 PyErr_SetString(PyExc_OverflowError, "string is too long");
1027 return NULL;
1028 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001029 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001030 if (kind == sizeof(Tcl_UniChar))
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001031 return Tcl_NewUnicodeObj(inbuf, (int)size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001032 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001033 outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 /* Else overflow occurred, and we take the next exit */
1035 if (!outbuf) {
1036 PyErr_NoMemory();
1037 return NULL;
1038 }
1039 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001040 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1041 /* We cannot test for sizeof(Tcl_UniChar) directly,
1042 so we test for UTF-8 size instead. */
1043#if TCL_UTF_MAX == 3
1044 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001046 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001047 "character U+%x is above the range "
1048 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001049 ch);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001050 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 return NULL;
1052 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001053#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001054 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001056 result = Tcl_NewUnicodeObj(outbuf, (int)size);
Victor Stinneree6c3c72014-09-11 17:50:21 +02001057 PyMem_Free(outbuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001060
1061 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 Tcl_Obj *v = ((PyTclObject*)value)->value;
1063 Tcl_IncrRefCount(v);
1064 return v;
1065 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001066
1067 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 PyObject *v = PyObject_Str(value);
1069 if (!v)
1070 return 0;
1071 result = AsObj(v);
1072 Py_DECREF(v);
1073 return result;
1074 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001075}
1076
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001077static PyObject *
1078fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1079{
1080 int boolValue;
1081 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1082 return Tkinter_Error(tkapp);
1083 return PyBool_FromLong(boolValue);
1084}
1085
Martin v. Löwisffad6332002-11-26 09:28:05 +00001086static PyObject*
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001087fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1088{
1089 Tcl_WideInt wideValue;
1090 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1091#ifdef HAVE_LONG_LONG
1092 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1093 return PyLong_FromLongLong(wideValue);
1094#endif
1095 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1096 sizeof(wideValue),
1097 PY_LITTLE_ENDIAN,
1098 /* signed */ 1);
1099 }
1100 return NULL;
1101}
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001102
1103#ifdef HAVE_LIBTOMMAMTH
1104static PyObject*
1105fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1106{
1107 mp_int bigValue;
1108 unsigned long numBytes;
1109 unsigned char *bytes;
1110 PyObject *res;
1111
1112 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1113 return Tkinter_Error(tkapp);
1114 numBytes = mp_unsigned_bin_size(&bigValue);
1115 bytes = PyMem_Malloc(numBytes);
1116 if (bytes == NULL) {
1117 mp_clear(&bigValue);
1118 return PyErr_NoMemory();
1119 }
1120 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1121 &numBytes) != MP_OKAY) {
1122 mp_clear(&bigValue);
1123 PyMem_Free(bytes);
1124 return PyErr_NoMemory();
1125 }
1126 res = _PyLong_FromByteArray(bytes, numBytes,
1127 /* big-endian */ 0,
1128 /* unsigned */ 0);
1129 PyMem_Free(bytes);
1130 if (res != NULL && bigValue.sign == MP_NEG) {
1131 PyObject *res2 = PyNumber_Negative(res);
1132 Py_DECREF(res);
1133 res = res2;
1134 }
1135 mp_clear(&bigValue);
1136 return res;
1137}
1138#endif
1139
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140static PyObject*
1141FromObj(PyObject* tkapp, Tcl_Obj *value)
1142{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 PyObject *result = NULL;
1144 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001145 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001148 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001150
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001151 if (value->typePtr == app->BooleanType ||
1152 value->typePtr == app->OldBooleanType) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001153 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001154 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 if (value->typePtr == app->ByteArrayType) {
1157 int size;
1158 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1159 return PyBytes_FromStringAndSize(data, size);
1160 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 if (value->typePtr == app->DoubleType) {
1163 return PyFloat_FromDouble(value->internalRep.doubleValue);
1164 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001166 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001167 long longValue;
1168 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1169 return PyLong_FromLong(longValue);
1170 /* If there is an error in the long conversion,
1171 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001173
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001174 if (value->typePtr == app->IntType ||
1175 value->typePtr == app->WideIntType) {
1176 result = fromWideIntObj(tkapp, value);
1177 if (result != NULL || PyErr_Occurred())
1178 return result;
1179 Tcl_ResetResult(interp);
1180 /* If there is an error in the wideInt conversion,
1181 fall through to bignum handling. */
1182 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001183
1184#ifdef HAVE_LIBTOMMAMTH
1185 if (value->typePtr == app->IntType ||
1186 value->typePtr == app->WideIntType ||
1187 value->typePtr == app->BignumType) {
1188 return fromBignumObj(tkapp, value);
1189 }
1190#endif
1191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 if (value->typePtr == app->ListType) {
1193 int size;
1194 int i, status;
1195 PyObject *elem;
1196 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001197
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001198 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001199 if (status == TCL_ERROR)
1200 return Tkinter_Error(tkapp);
1201 result = PyTuple_New(size);
1202 if (!result)
1203 return NULL;
1204 for (i = 0; i < size; i++) {
Serhiy Storchakaf07a4b62015-03-23 00:47:45 +02001205 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 if (status == TCL_ERROR) {
1207 Py_DECREF(result);
1208 return Tkinter_Error(tkapp);
1209 }
1210 elem = FromObj(tkapp, tcl_elem);
1211 if (!elem) {
1212 Py_DECREF(result);
1213 return NULL;
1214 }
1215 PyTuple_SetItem(result, i, elem);
1216 }
1217 return result;
1218 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001219
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 if (value->typePtr == app->ProcBodyType) {
1221 /* fall through: return tcl object. */
1222 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001225 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001226 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001227 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001228 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001229
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001230#if TK_VERSION_HEX >= 0x08050000
1231 if (app->BooleanType == NULL &&
1232 strcmp(value->typePtr->name, "booleanString") == 0) {
1233 /* booleanString type is not registered in Tcl */
1234 app->BooleanType = value->typePtr;
1235 return fromBoolean(tkapp, value);
1236 }
1237#endif
1238
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001239#ifdef HAVE_LIBTOMMAMTH
1240 if (app->BignumType == NULL &&
1241 strcmp(value->typePtr->name, "bignum") == 0) {
1242 /* bignum type is not registered in Tcl */
1243 app->BignumType = value->typePtr;
1244 return fromBignumObj(tkapp, value);
1245 }
1246#endif
1247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001249}
1250
Benjamin Peterson5879d412009-03-30 14:51:56 +00001251#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253TCL_DECLARE_MUTEX(call_mutex)
1254
1255typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 Tcl_Event ev; /* Must be first */
1257 TkappObject *self;
1258 PyObject *args;
1259 int flags;
1260 PyObject **res;
1261 PyObject **exc_type, **exc_value, **exc_tb;
1262 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001264#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265
1266void
1267Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001268{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 int i;
1270 for (i = 0; i < objc; i++)
1271 Tcl_DecrRefCount(objv[i]);
1272 if (objv != objStore)
Victor Stinneree6c3c72014-09-11 17:50:21 +02001273 PyMem_Free(objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274}
Guido van Rossum18468821994-06-20 07:49:28 +00001275
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001276/* Convert Python objects to Tcl objects. This must happen in the
1277 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001278
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279static Tcl_Obj**
1280Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1281{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001283 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 if (args == NULL)
1285 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001286
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001287 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 objv[0] = AsObj(args);
1289 if (objv[0] == 0)
1290 goto finally;
1291 objc = 1;
1292 Tcl_IncrRefCount(objv[0]);
1293 }
1294 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001295 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001298 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001299 PyErr_SetString(PyExc_OverflowError,
1300 PyTuple_Check(args) ? "tuple is too long" :
1301 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001302 return NULL;
1303 }
Victor Stinneree6c3c72014-09-11 17:50:21 +02001304 objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001305 if (objv == NULL) {
1306 PyErr_NoMemory();
1307 objc = 0;
1308 goto finally;
1309 }
1310 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001313 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314 if (v == Py_None) {
1315 objc = i;
1316 break;
1317 }
1318 objv[i] = AsObj(v);
1319 if (!objv[i]) {
1320 /* Reset objc, so it attempts to clear
1321 objects only up to i. */
1322 objc = i;
1323 goto finally;
1324 }
1325 Tcl_IncrRefCount(objv[i]);
1326 }
1327 }
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001328 *pobjc = (int)objc;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330finally:
Serhiy Storchaka26861b02015-02-16 20:52:17 +02001331 Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001332 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001333}
Guido van Rossum212643f1998-04-29 16:22:14 +00001334
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001336
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001337static PyObject*
1338Tkapp_CallResult(TkappObject *self)
1339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001341 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 /* Not sure whether the IncrRef is necessary, but something
1344 may overwrite the interpreter result while we are
1345 converting it. */
1346 Tcl_IncrRefCount(value);
1347 res = FromObj((PyObject*)self, value);
1348 Tcl_DecrRefCount(value);
1349 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001350 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 }
1352 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001353}
Guido van Rossum632de272000-03-29 00:19:50 +00001354
Benjamin Peterson5879d412009-03-30 14:51:56 +00001355#ifdef WITH_THREAD
1356
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357/* Tkapp_CallProc is the event procedure that is executed in the context of
1358 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1359 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001360
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001361static int
1362Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1363{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 Tcl_Obj *objStore[ARGSZ];
1365 Tcl_Obj **objv;
1366 int objc;
1367 int i;
1368 ENTER_PYTHON
1369 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1370 if (!objv) {
1371 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1372 *(e->res) = NULL;
1373 }
1374 LEAVE_PYTHON
1375 if (!objv)
1376 goto done;
1377 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1378 ENTER_PYTHON
1379 if (i == TCL_ERROR) {
1380 *(e->res) = NULL;
1381 *(e->exc_type) = NULL;
1382 *(e->exc_tb) = NULL;
1383 *(e->exc_value) = PyObject_CallFunction(
1384 Tkinter_TclError, "s",
1385 Tcl_GetStringResult(e->self->interp));
1386 }
1387 else {
1388 *(e->res) = Tkapp_CallResult(e->self);
1389 }
1390 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001393done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001394 /* Wake up calling thread. */
1395 Tcl_MutexLock(&call_mutex);
1396 Tcl_ConditionNotify(e->done);
1397 Tcl_MutexUnlock(&call_mutex);
1398 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001399}
1400
Benjamin Peterson5879d412009-03-30 14:51:56 +00001401#endif
1402
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403/* This is the main entry point for calling a Tcl command.
1404 It supports three cases, with regard to threading:
1405 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1406 the context of the calling thread.
1407 2. Tcl is threaded, caller of the command is in the interpreter thread:
1408 Execute the command in the calling thread. Since the Tcl lock will
1409 not be used, we can merge that with case 1.
1410 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1411 the interpreter thread. Allocation of Tcl objects needs to occur in the
1412 interpreter thread, so we ship the PyObject* args to the target thread,
1413 and perform processing there. */
1414
1415static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001416Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001417{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 Tcl_Obj *objStore[ARGSZ];
1419 Tcl_Obj **objv = NULL;
1420 int objc, i;
1421 PyObject *res = NULL;
1422 TkappObject *self = (TkappObject*)selfptr;
1423 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 /* If args is a single tuple, replace with contents of tuple */
1426 if (1 == PyTuple_Size(args)){
1427 PyObject* item = PyTuple_GetItem(args, 0);
1428 if (PyTuple_Check(item))
1429 args = item;
1430 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001431#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1433 /* We cannot call the command directly. Instead, we must
1434 marshal the parameters to the interpreter thread. */
1435 Tkapp_CallEvent *ev;
1436 Tcl_Condition cond = NULL;
1437 PyObject *exc_type, *exc_value, *exc_tb;
1438 if (!WaitForMainloop(self))
1439 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001440 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1441 if (ev == NULL) {
1442 PyErr_NoMemory();
1443 return NULL;
1444 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1446 ev->self = self;
1447 ev->args = args;
1448 ev->res = &res;
1449 ev->exc_type = &exc_type;
1450 ev->exc_value = &exc_value;
1451 ev->exc_tb = &exc_tb;
1452 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001456 if (res == NULL) {
1457 if (exc_type)
1458 PyErr_Restore(exc_type, exc_value, exc_tb);
1459 else
1460 PyErr_SetObject(Tkinter_TclError, exc_value);
1461 }
1462 Tcl_ConditionFinalize(&cond);
1463 }
1464 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001465#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001466 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 objv = Tkapp_CallArgs(args, objStore, &objc);
1469 if (!objv)
1470 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001476 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001478 if (i == TCL_ERROR)
1479 Tkinter_Error(selfptr);
1480 else
1481 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 Tkapp_CallDeallocArgs(objv, objStore, objc);
1486 }
1487 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001488}
1489
1490
1491static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001492Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001493{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494 char *script;
1495 PyObject *res = NULL;
1496 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 if (!PyArg_ParseTuple(args, "s:eval", &script))
1499 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001500
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001501 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 ENTER_TCL
1505 err = Tcl_Eval(Tkapp_Interp(self), script);
1506 ENTER_OVERLAP
1507 if (err == TCL_ERROR)
1508 res = Tkinter_Error(self);
1509 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001510 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 LEAVE_OVERLAP_TCL
1512 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001513}
1514
1515static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001516Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001517{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 char *fileName;
1519 PyObject *res = NULL;
1520 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1523 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001524
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001525 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001528 ENTER_TCL
1529 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1530 ENTER_OVERLAP
1531 if (err == TCL_ERROR)
1532 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001534 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 LEAVE_OVERLAP_TCL
1536 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001537}
1538
1539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001540Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 char *script;
1543 PyObject *res = NULL;
1544 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001545
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001546 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001548
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001549 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 ENTER_TCL
1553 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1554 ENTER_OVERLAP
1555 if (err == TCL_ERROR)
1556 res = Tkinter_Error(self);
1557 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001558 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 LEAVE_OVERLAP_TCL
1560 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001561}
1562
1563static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001564Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001565{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1569 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001570 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 ENTER_TCL
1574 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1575 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001576
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001577 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001578}
1579
Barry Warsawfa701a81997-01-16 00:15:11 +00001580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581
Guido van Rossum18468821994-06-20 07:49:28 +00001582/** Tcl Variable **/
1583
Benjamin Peterson5879d412009-03-30 14:51:56 +00001584typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1585
1586#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587TCL_DECLARE_MUTEX(var_mutex)
1588
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001589typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 Tcl_Event ev; /* must be first */
1591 PyObject *self;
1592 PyObject *args;
1593 int flags;
1594 EventFunc func;
1595 PyObject **res;
1596 PyObject **exc_type;
1597 PyObject **exc_val;
1598 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001599} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001600#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001601
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001602static int
1603varname_converter(PyObject *in, void *_out)
1604{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001605 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 char **out = (char**)_out;
1607 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001608 if (PyBytes_Size(in) > INT_MAX) {
1609 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1610 return 0;
1611 }
1612 s = PyBytes_AsString(in);
Victor Stinner706768c2014-08-16 01:03:39 +02001613 if (strlen(s) != (size_t)PyBytes_Size(in)) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001614 PyErr_SetString(PyExc_ValueError, "embedded null byte");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001615 return 0;
1616 }
1617 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001618 return 1;
1619 }
1620 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001621 Py_ssize_t size;
1622 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001623 if (s == NULL) {
1624 return 0;
1625 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001626 if (size > INT_MAX) {
1627 PyErr_SetString(PyExc_OverflowError, "string is too long");
1628 return 0;
1629 }
Victor Stinner706768c2014-08-16 01:03:39 +02001630 if (strlen(s) != (size_t)size) {
Serhiy Storchakad8a14472014-09-06 20:07:17 +03001631 PyErr_SetString(PyExc_ValueError, "embedded null character");
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001632 return 0;
1633 }
1634 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 return 1;
1636 }
1637 if (PyTclObject_Check(in)) {
1638 *out = PyTclObject_TclString(in);
1639 return 1;
1640 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001641 PyErr_Format(PyExc_TypeError,
1642 "must be str, bytes or Tcl_Obj, not %.50s",
1643 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001645}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001646
Benjamin Peterson5879d412009-03-30 14:51:56 +00001647#ifdef WITH_THREAD
1648
Martin v. Löwis59683e82008-06-13 07:50:45 +00001649static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001650var_perform(VarEvent *ev)
1651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1653 if (!*(ev->res)) {
1654 PyObject *exc, *val, *tb;
1655 PyErr_Fetch(&exc, &val, &tb);
1656 PyErr_NormalizeException(&exc, &val, &tb);
1657 *(ev->exc_type) = exc;
1658 *(ev->exc_val) = val;
1659 Py_DECREF(tb);
1660 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001661
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001662}
1663
1664static int
1665var_proc(VarEvent* ev, int flags)
1666{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 ENTER_PYTHON
1668 var_perform(ev);
1669 Tcl_MutexLock(&var_mutex);
1670 Tcl_ConditionNotify(ev->cond);
1671 Tcl_MutexUnlock(&var_mutex);
1672 LEAVE_PYTHON
1673 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001674}
1675
Benjamin Peterson5879d412009-03-30 14:51:56 +00001676#endif
1677
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001678static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001679var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001680{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001681#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 TkappObject *self = (TkappObject*)selfptr;
1683 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 VarEvent *ev;
1685 PyObject *res, *exc_type, *exc_val;
1686 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001688 /* The current thread is not the interpreter thread. Marshal
1689 the call to the interpreter thread, then wait for
1690 completion. */
1691 if (!WaitForMainloop(self))
1692 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001693
Serhiy Storchaka07940882014-09-11 10:38:54 +03001694 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1695 if (ev == NULL) {
1696 PyErr_NoMemory();
1697 return NULL;
1698 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001699 ev->self = selfptr;
1700 ev->args = args;
1701 ev->flags = flags;
1702 ev->func = func;
1703 ev->res = &res;
1704 ev->exc_type = &exc_type;
1705 ev->exc_val = &exc_val;
1706 ev->cond = &cond;
1707 ev->ev.proc = (Tcl_EventProc*)var_proc;
1708 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1709 Tcl_ConditionFinalize(&cond);
1710 if (!res) {
1711 PyErr_SetObject(exc_type, exc_val);
1712 Py_DECREF(exc_type);
1713 Py_DECREF(exc_val);
1714 return NULL;
1715 }
1716 return res;
1717 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001718#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001719 /* Tcl is not threaded, or this is the interpreter thread. */
1720 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001721}
1722
Guido van Rossum18468821994-06-20 07:49:28 +00001723static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001724SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001725{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 char *name1, *name2;
1727 PyObject *newValue;
1728 PyObject *res = NULL;
1729 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001730
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001731 switch (PyTuple_GET_SIZE(args)) {
1732 case 2:
1733 if (!PyArg_ParseTuple(args, "O&O:setvar",
1734 varname_converter, &name1, &newValue))
1735 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001736 /* XXX Acquire tcl lock??? */
1737 newval = AsObj(newValue);
1738 if (newval == NULL)
1739 return NULL;
1740 ENTER_TCL
1741 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1742 newval, flags);
1743 ENTER_OVERLAP
1744 if (!ok)
1745 Tkinter_Error(self);
1746 else {
1747 res = Py_None;
1748 Py_INCREF(res);
1749 }
1750 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001751 break;
1752 case 3:
1753 if (!PyArg_ParseTuple(args, "ssO:setvar",
1754 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001756 CHECK_STRING_LENGTH(name1);
1757 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001758 /* XXX must hold tcl lock already??? */
1759 newval = AsObj(newValue);
1760 ENTER_TCL
1761 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1762 ENTER_OVERLAP
1763 if (!ok)
1764 Tkinter_Error(self);
1765 else {
1766 res = Py_None;
1767 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001769 LEAVE_OVERLAP_TCL
1770 break;
1771 default:
1772 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1773 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 }
1775 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
1778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001782}
1783
1784static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001785Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001786{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
Barry Warsawfa701a81997-01-16 00:15:11 +00001790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791
Guido van Rossum18468821994-06-20 07:49:28 +00001792static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001793GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001795 char *name1, *name2=NULL;
1796 PyObject *res = NULL;
1797 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001798
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1800 varname_converter, &name1, &name2))
1801 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001803 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804 ENTER_TCL
1805 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1806 ENTER_OVERLAP
1807 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001808 PyErr_SetString(Tkinter_TclError,
1809 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 } else {
1811 if (((TkappObject*)self)->wantobjects) {
1812 res = FromObj(self, tres);
1813 }
1814 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001815 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001816 }
1817 }
1818 LEAVE_OVERLAP_TCL
1819 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
1822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001826}
1827
1828static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001829Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001830{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001832}
1833
Barry Warsawfa701a81997-01-16 00:15:11 +00001834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001835
Guido van Rossum18468821994-06-20 07:49:28 +00001836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 char *name1, *name2=NULL;
1840 int code;
1841 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001843 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1844 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001845
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001846 CHECK_STRING_LENGTH(name1);
1847 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848 ENTER_TCL
1849 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1850 ENTER_OVERLAP
1851 if (code == TCL_ERROR)
1852 res = Tkinter_Error(self);
1853 else {
1854 Py_INCREF(Py_None);
1855 res = Py_None;
1856 }
1857 LEAVE_OVERLAP_TCL
1858 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001859}
1860
1861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001862Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001863{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001864 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001865}
1866
1867static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001868Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001869{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001870 return var_invoke(UnsetVar, self, args,
1871 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
Barry Warsawfa701a81997-01-16 00:15:11 +00001874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001875
Guido van Rossum18468821994-06-20 07:49:28 +00001876/** Tcl to Python **/
1877
1878static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001879Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001880{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001882 Tcl_Obj *value;
1883 PyObject *result;
Guido van Rossum18468821994-06-20 07:49:28 +00001884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001885 if (PyTuple_Size(args) == 1) {
1886 PyObject* o = PyTuple_GetItem(args, 0);
1887 if (PyLong_Check(o)) {
1888 Py_INCREF(o);
1889 return o;
1890 }
1891 }
1892 if (!PyArg_ParseTuple(args, "s:getint", &s))
1893 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001894 CHECK_STRING_LENGTH(s);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001895 value = Tcl_NewStringObj(s, -1);
1896 if (value == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001897 return Tkinter_Error(self);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001898 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1899 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1900
1901 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1902 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1903 */
1904#ifdef HAVE_LIBTOMMAMTH
1905 result = fromBignumObj(self, value);
1906#else
1907 result = fromWideIntObj(self, value);
1908#endif
1909 Tcl_DecrRefCount(value);
1910 if (result != NULL || PyErr_Occurred())
1911 return result;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001912 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001913}
1914
1915static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001916Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001918 char *s;
1919 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001921 if (PyTuple_Size(args) == 1) {
1922 PyObject *o = PyTuple_GetItem(args, 0);
1923 if (PyFloat_Check(o)) {
1924 Py_INCREF(o);
1925 return o;
1926 }
1927 }
1928 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1929 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001930 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001931 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1932 return Tkinter_Error(self);
1933 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001934}
1935
1936static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001937Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001938{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 char *s;
1940 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001942 if (PyTuple_Size(args) == 1) {
1943 PyObject *o = PyTuple_GetItem(args, 0);
1944 if (PyLong_Check(o)) {
1945 Py_INCREF(o);
1946 return o;
1947 }
1948 }
1949 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1950 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001951 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1953 return Tkinter_Error(self);
1954 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001955}
1956
1957static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001958Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001959{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 char *s;
1961 PyObject *res = NULL;
1962 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1965 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001966
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001967 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 ENTER_TCL
1971 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1972 ENTER_OVERLAP
1973 if (retval == TCL_ERROR)
1974 res = Tkinter_Error(self);
1975 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001976 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 LEAVE_OVERLAP_TCL
1978 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001979}
1980
1981static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001982Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001983{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 char *s;
1985 PyObject *res = NULL;
1986 int retval;
1987 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1990 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001991
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001992 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 ENTER_TCL
1996 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1997 ENTER_OVERLAP
1998 if (retval == TCL_ERROR)
1999 res = Tkinter_Error(self);
2000 else
2001 res = Py_BuildValue("l", v);
2002 LEAVE_OVERLAP_TCL
2003 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002004}
2005
2006static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002007Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 char *s;
2010 PyObject *res = NULL;
2011 double v;
2012 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2015 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002016 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 CHECK_TCL_APPARTMENT;
2018 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2019 ENTER_TCL
2020 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2021 ENTER_OVERLAP
2022 PyFPE_END_PROTECT(retval)
2023 if (retval == TCL_ERROR)
2024 res = Tkinter_Error(self);
2025 else
2026 res = Py_BuildValue("d", v);
2027 LEAVE_OVERLAP_TCL
2028 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002029}
2030
2031static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002032Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 char *s;
2035 PyObject *res = NULL;
2036 int retval;
2037 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2040 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002041 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 CHECK_TCL_APPARTMENT;
2043 ENTER_TCL
2044 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2045 ENTER_OVERLAP
2046 if (retval == TCL_ERROR)
2047 res = Tkinter_Error(self);
2048 else
2049 res = Py_BuildValue("i", v);
2050 LEAVE_OVERLAP_TCL
2051 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002052}
2053
Barry Warsawfa701a81997-01-16 00:15:11 +00002054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055
Guido van Rossum18468821994-06-20 07:49:28 +00002056static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002057Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 char *list;
2060 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002061 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002062 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002064
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002065 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2066 return NULL;
2067 if (PyTclObject_Check(arg)) {
2068 int objc;
2069 Tcl_Obj **objv;
2070 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2071 ((PyTclObject*)arg)->value,
2072 &objc, &objv) == TCL_ERROR) {
2073 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002075 if (!(v = PyTuple_New(objc)))
2076 return NULL;
2077 for (i = 0; i < objc; i++) {
2078 PyObject *s = FromObj(self, objv[i]);
2079 if (!s || PyTuple_SetItem(v, i, s)) {
2080 Py_DECREF(v);
2081 return NULL;
2082 }
2083 }
2084 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002086 if (PyTuple_Check(arg)) {
2087 Py_INCREF(arg);
2088 return arg;
2089 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002090 if (PyList_Check(arg)) {
2091 return PySequence_Tuple(arg);
2092 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2095 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002096
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002097 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002098 if (Tcl_SplitList(Tkapp_Interp(self), list,
2099 &argc, &argv) == TCL_ERROR) {
2100 PyMem_Free(list);
2101 return Tkinter_Error(self);
2102 }
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 if (!(v = PyTuple_New(argc)))
2105 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002108 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002109 if (!s || PyTuple_SetItem(v, i, s)) {
2110 Py_DECREF(v);
2111 v = NULL;
2112 goto finally;
2113 }
2114 }
Guido van Rossum18468821994-06-20 07:49:28 +00002115
Barry Warsawfa701a81997-01-16 00:15:11 +00002116 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002117 ckfree(FREECAST argv);
2118 PyMem_Free(list);
2119 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002120}
2121
2122static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002123Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002124{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002125 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002126 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002127
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002128 if (!PyArg_ParseTuple(args, "O:split", &arg))
2129 return NULL;
2130 if (PyTclObject_Check(arg)) {
2131 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2132 int objc;
2133 Tcl_Obj **objv;
2134 int i;
2135 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2136 &objc, &objv) == TCL_ERROR) {
2137 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002139 if (objc == 0)
2140 return PyUnicode_FromString("");
2141 if (objc == 1)
2142 return FromObj(self, objv[0]);
2143 if (!(v = PyTuple_New(objc)))
2144 return NULL;
2145 for (i = 0; i < objc; i++) {
2146 PyObject *s = FromObj(self, objv[i]);
2147 if (!s || PyTuple_SetItem(v, i, s)) {
2148 Py_DECREF(v);
2149 return NULL;
2150 }
2151 }
2152 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002153 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002154 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002155 return SplitObj(arg);
2156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2158 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002159 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 v = Split(list);
2161 PyMem_Free(list);
2162 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002163}
2164
Barry Warsawfa701a81997-01-16 00:15:11 +00002165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166
Guido van Rossum18468821994-06-20 07:49:28 +00002167/** Tcl Command **/
2168
Guido van Rossum00d93061998-05-28 23:06:38 +00002169/* Client data struct */
2170typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 PyObject *self;
2172 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002173} PythonCmd_ClientData;
2174
2175static int
Fred Drake509d79a2000-07-08 04:04:38 +00002176PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002178 errorInCmd = 1;
2179 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2180 LEAVE_PYTHON
2181 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002182}
2183
Guido van Rossum18468821994-06-20 07:49:28 +00002184/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002185 * function or method.
2186 */
Guido van Rossum18468821994-06-20 07:49:28 +00002187static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002188PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002191 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 int i, rv;
2193 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002196
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 /* TBD: no error checking here since we know, via the
2198 * Tkapp_CreateCommand() that the client data is a two-tuple
2199 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 /* Create argument list (argv1, ..., argvN) */
2203 if (!(arg = PyTuple_New(argc - 1)))
2204 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002207 PyObject *s = unicodeFromTclString(argv[i + 1]);
2208 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002209 Py_DECREF(arg);
2210 return PythonCmd_Error(interp);
2211 }
2212 }
2213 res = PyEval_CallObject(func, arg);
2214 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002216 if (res == NULL)
2217 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 obj_res = AsObj(res);
2220 if (obj_res == NULL) {
2221 Py_DECREF(res);
2222 return PythonCmd_Error(interp);
2223 }
2224 else {
2225 Tcl_SetObjResult(interp, obj_res);
2226 rv = TCL_OK;
2227 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002232
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002234}
2235
2236static void
Fred Drake509d79a2000-07-08 04:04:38 +00002237PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002238{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002241 ENTER_PYTHON
2242 Py_XDECREF(data->self);
2243 Py_XDECREF(data->func);
2244 PyMem_DEL(data);
2245 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002246}
2247
Barry Warsawfa701a81997-01-16 00:15:11 +00002248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002249
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002250
Benjamin Peterson5879d412009-03-30 14:51:56 +00002251#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002252TCL_DECLARE_MUTEX(command_mutex)
2253
2254typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 Tcl_Event ev;
2256 Tcl_Interp* interp;
2257 char *name;
2258 int create;
2259 int *status;
2260 ClientData *data;
2261 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002262} CommandEvent;
2263
2264static int
2265Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002266{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 if (ev->create)
2268 *ev->status = Tcl_CreateCommand(
2269 ev->interp, ev->name, PythonCmd,
2270 ev->data, PythonCmdDelete) == NULL;
2271 else
2272 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2273 Tcl_MutexLock(&command_mutex);
2274 Tcl_ConditionNotify(ev->done);
2275 Tcl_MutexUnlock(&command_mutex);
2276 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002277}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002278#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002279
2280static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002281Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002282{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 TkappObject *self = (TkappObject*)selfptr;
2284 PythonCmd_ClientData *data;
2285 char *cmdName;
2286 PyObject *func;
2287 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002288
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2290 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002291 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 if (!PyCallable_Check(func)) {
2293 PyErr_SetString(PyExc_TypeError, "command not callable");
2294 return NULL;
2295 }
Guido van Rossum18468821994-06-20 07:49:28 +00002296
Martin v. Löwisa9656492003-03-30 08:44:58 +00002297#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002298 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2299 !WaitForMainloop(self))
2300 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002301#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 data = PyMem_NEW(PythonCmd_ClientData, 1);
2304 if (!data)
2305 return PyErr_NoMemory();
2306 Py_INCREF(self);
2307 Py_INCREF(func);
2308 data->self = selfptr;
2309 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002310#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2312 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002313 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2314 if (ev == NULL) {
2315 PyErr_NoMemory();
2316 PyMem_DEL(data);
2317 return NULL;
2318 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2320 ev->interp = self->interp;
2321 ev->create = 1;
2322 ev->name = cmdName;
2323 ev->data = (ClientData)data;
2324 ev->status = &err;
2325 ev->done = &cond;
2326 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2327 Tcl_ConditionFinalize(&cond);
2328 }
2329 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002330#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 {
2332 ENTER_TCL
2333 err = Tcl_CreateCommand(
2334 Tkapp_Interp(self), cmdName, PythonCmd,
2335 (ClientData)data, PythonCmdDelete) == NULL;
2336 LEAVE_TCL
2337 }
2338 if (err) {
2339 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2340 PyMem_DEL(data);
2341 return NULL;
2342 }
Guido van Rossum18468821994-06-20 07:49:28 +00002343
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002344 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002345}
2346
Barry Warsawfa701a81997-01-16 00:15:11 +00002347
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348
Guido van Rossum18468821994-06-20 07:49:28 +00002349static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002350Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 TkappObject *self = (TkappObject*)selfptr;
2353 char *cmdName;
2354 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002356 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2357 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002358 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002359
2360#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2362 Tcl_Condition cond = NULL;
2363 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002364 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2365 if (ev == NULL) {
2366 PyErr_NoMemory();
2367 return NULL;
2368 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2370 ev->interp = self->interp;
2371 ev->create = 0;
2372 ev->name = cmdName;
2373 ev->status = &err;
2374 ev->done = &cond;
2375 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2376 &command_mutex);
2377 Tcl_ConditionFinalize(&cond);
2378 }
2379 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002380#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 {
2382 ENTER_TCL
2383 err = Tcl_DeleteCommand(self->interp, cmdName);
2384 LEAVE_TCL
2385 }
2386 if (err == -1) {
2387 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2388 return NULL;
2389 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002390 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002391}
2392
Barry Warsawfa701a81997-01-16 00:15:11 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394
Guido van Rossum00d93061998-05-28 23:06:38 +00002395#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002396/** File Handler **/
2397
Guido van Rossum00d93061998-05-28 23:06:38 +00002398typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399 PyObject *func;
2400 PyObject *file;
2401 int id;
2402 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002403} FileHandler_ClientData;
2404
2405static FileHandler_ClientData *HeadFHCD;
2406
2407static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002408NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002409{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002410 FileHandler_ClientData *p;
2411 p = PyMem_NEW(FileHandler_ClientData, 1);
2412 if (p != NULL) {
2413 Py_XINCREF(func);
2414 Py_XINCREF(file);
2415 p->func = func;
2416 p->file = file;
2417 p->id = id;
2418 p->next = HeadFHCD;
2419 HeadFHCD = p;
2420 }
2421 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002422}
2423
2424static void
Fred Drake509d79a2000-07-08 04:04:38 +00002425DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002426{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 pp = &HeadFHCD;
2430 while ((p = *pp) != NULL) {
2431 if (p->id == id) {
2432 *pp = p->next;
2433 Py_XDECREF(p->func);
2434 Py_XDECREF(p->file);
2435 PyMem_DEL(p);
2436 }
2437 else
2438 pp = &p->next;
2439 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002440}
2441
Guido van Rossuma597dde1995-01-10 20:56:29 +00002442static void
Fred Drake509d79a2000-07-08 04:04:38 +00002443FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2446 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 ENTER_PYTHON
2449 func = data->func;
2450 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002452 arg = Py_BuildValue("(Oi)", file, (long) mask);
2453 res = PyEval_CallObject(func, arg);
2454 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 if (res == NULL) {
2457 errorInCmd = 1;
2458 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2459 }
2460 Py_XDECREF(res);
2461 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002462}
2463
Guido van Rossum18468821994-06-20 07:49:28 +00002464static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002465Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2466 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 FileHandler_ClientData *data;
2469 PyObject *file, *func;
2470 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002472 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2473 &file, &mask, &func))
2474 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 tfile = PyObject_AsFileDescriptor(file);
2479 if (tfile < 0)
2480 return NULL;
2481 if (!PyCallable_Check(func)) {
2482 PyErr_SetString(PyExc_TypeError, "bad argument list");
2483 return NULL;
2484 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 data = NewFHCD(func, file, tfile);
2487 if (data == NULL)
2488 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 /* Ought to check for null Tcl_File object... */
2491 ENTER_TCL
2492 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2493 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002494 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002495}
2496
2497static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002498Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002499{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 PyObject *file;
2501 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2504 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 tfile = PyObject_AsFileDescriptor(file);
2509 if (tfile < 0)
2510 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 /* Ought to check for null Tcl_File object... */
2515 ENTER_TCL
2516 Tcl_DeleteFileHandler(tfile);
2517 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002518 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002519}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002520#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002523/**** Tktt Object (timer token) ****/
2524
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002525static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002526
Guido van Rossum00d93061998-05-28 23:06:38 +00002527typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 PyObject_HEAD
2529 Tcl_TimerToken token;
2530 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002531} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002532
2533static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002534Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002535{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 TkttObject *v = (TkttObject *)self;
2537 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2540 return NULL;
2541 if (v->token != NULL) {
2542 Tcl_DeleteTimerHandler(v->token);
2543 v->token = NULL;
2544 }
2545 if (func != NULL) {
2546 v->func = NULL;
2547 Py_DECREF(func);
2548 Py_DECREF(v); /* See Tktt_New() */
2549 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002550 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002551}
2552
2553static PyMethodDef Tktt_methods[] =
2554{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002555 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2556 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002557};
2558
2559static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002560Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002563
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002564 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002565 if (v == NULL)
2566 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002567 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 Py_INCREF(func);
2570 v->token = NULL;
2571 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573 /* Extra reference, deleted when called or when handler is deleted */
2574 Py_INCREF(v);
2575 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002576}
2577
2578static void
Fred Drake509d79a2000-07-08 04:04:38 +00002579Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002580{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 TkttObject *v = (TkttObject *)self;
2582 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002583 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002587 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002588 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002589}
2590
Guido van Rossum597ac201998-05-12 14:36:19 +00002591static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002592Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002593{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002595 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2596 v,
2597 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002598}
2599
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002600static PyType_Slot Tktt_Type_slots[] = {
2601 {Py_tp_dealloc, Tktt_Dealloc},
2602 {Py_tp_repr, Tktt_Repr},
2603 {Py_tp_methods, Tktt_methods},
2604 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002605};
2606
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002607static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002608 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002609 sizeof(TkttObject),
2610 0,
2611 Py_TPFLAGS_DEFAULT,
2612 Tktt_Type_slots,
2613};
Barry Warsawfa701a81997-01-16 00:15:11 +00002614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002615
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002616/** Timer Handler **/
2617
2618static void
Fred Drake509d79a2000-07-08 04:04:38 +00002619TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002621 TkttObject *v = (TkttObject *)clientData;
2622 PyObject *func = v->func;
2623 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 if (func == NULL)
2626 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 res = PyEval_CallObject(func, NULL);
2633 Py_DECREF(func);
2634 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 if (res == NULL) {
2637 errorInCmd = 1;
2638 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2639 }
2640 else
2641 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002643 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002644}
2645
2646static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002647Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002648{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002649 int milliseconds;
2650 PyObject *func;
2651 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002653 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2654 &milliseconds, &func))
2655 return NULL;
2656 if (!PyCallable_Check(func)) {
2657 PyErr_SetString(PyExc_TypeError, "bad argument list");
2658 return NULL;
2659 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002663 v = Tktt_New(func);
2664 if (v) {
2665 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2666 (ClientData)v);
2667 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002670}
2671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002672
Guido van Rossum18468821994-06-20 07:49:28 +00002673/** Event Loop **/
2674
Guido van Rossum18468821994-06-20 07:49:28 +00002675static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002676Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678 int threshold = 0;
2679 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002680#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002681 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002682#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2685 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 CHECK_TCL_APPARTMENT;
2688 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 quitMainLoop = 0;
2691 while (Tk_GetNumMainWindows() > threshold &&
2692 !quitMainLoop &&
2693 !errorInCmd)
2694 {
2695 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002696
2697#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 if (self->threaded) {
2699 /* Allow other Python threads to run. */
2700 ENTER_TCL
2701 result = Tcl_DoOneEvent(0);
2702 LEAVE_TCL
2703 }
2704 else {
2705 Py_BEGIN_ALLOW_THREADS
2706 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2707 tcl_tstate = tstate;
2708 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2709 tcl_tstate = NULL;
2710 if(tcl_lock)PyThread_release_lock(tcl_lock);
2711 if (result == 0)
2712 Sleep(Tkinter_busywaitinterval);
2713 Py_END_ALLOW_THREADS
2714 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002715#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002717#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 if (PyErr_CheckSignals() != 0) {
2720 self->dispatching = 0;
2721 return NULL;
2722 }
2723 if (result < 0)
2724 break;
2725 }
2726 self->dispatching = 0;
2727 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 if (errorInCmd) {
2730 errorInCmd = 0;
2731 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2732 excInCmd = valInCmd = trbInCmd = NULL;
2733 return NULL;
2734 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002735 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002736}
2737
2738static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002739Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002740{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 int flags = 0;
2742 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2745 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002747 ENTER_TCL
2748 rv = Tcl_DoOneEvent(flags);
2749 LEAVE_TCL
2750 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002751}
2752
2753static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002754Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002755{
2756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 if (!PyArg_ParseTuple(args, ":quit"))
2758 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002759
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002760 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002761 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002762}
2763
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002764static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002765Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002766{
2767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 if (!PyArg_ParseTuple(args, ":interpaddr"))
2769 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002770
Victor Stinnere1040e22013-09-05 00:22:24 +02002771 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002772}
2773
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002775Tkapp_TkInit(PyObject *self, PyObject *args)
2776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 Tcl_Interp *interp = Tkapp_Interp(self);
2778 const char * _tk_exists = NULL;
2779 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002780
Guilherme Polob681df42009-02-09 22:33:59 +00002781#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2783 * first call failed.
2784 * To avoid the deadlock, we just refuse the second call through
2785 * a static variable.
2786 */
2787 if (tk_load_failed) {
2788 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2789 return NULL;
2790 }
Guilherme Polob681df42009-02-09 22:33:59 +00002791#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 /* We want to guard against calling Tk_Init() multiple times */
2794 CHECK_TCL_APPARTMENT;
2795 ENTER_TCL
2796 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2797 ENTER_OVERLAP
2798 if (err == TCL_ERROR) {
2799 /* This sets an exception, but we cannot return right
2800 away because we need to exit the overlap first. */
2801 Tkinter_Error(self);
2802 } else {
2803 _tk_exists = Tkapp_Result(self);
2804 }
2805 LEAVE_OVERLAP_TCL
2806 if (err == TCL_ERROR) {
2807 return NULL;
2808 }
2809 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2810 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002811 PyErr_SetString(Tkinter_TclError,
2812 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002813#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002815#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 return NULL;
2817 }
2818 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002819 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002820}
Barry Warsawfa701a81997-01-16 00:15:11 +00002821
Martin v. Löwisffad6332002-11-26 09:28:05 +00002822static PyObject *
2823Tkapp_WantObjects(PyObject *self, PyObject *args)
2824{
2825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 int wantobjects = -1;
2827 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2828 return NULL;
2829 if (wantobjects == -1)
2830 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2831 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002832
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002833 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002834}
2835
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002836static PyObject *
2837Tkapp_WillDispatch(PyObject *self, PyObject *args)
2838{
2839
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002841
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002842 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002843}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002844
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845
Guido van Rossum18468821994-06-20 07:49:28 +00002846/**** Tkapp Method List ****/
2847
2848static PyMethodDef Tkapp_methods[] =
2849{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2851 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2852 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002853 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002854 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2855 {"record", Tkapp_Record, METH_VARARGS},
2856 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2857 {"setvar", Tkapp_SetVar, METH_VARARGS},
2858 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2859 {"getvar", Tkapp_GetVar, METH_VARARGS},
2860 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2861 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2862 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2863 {"getint", Tkapp_GetInt, METH_VARARGS},
2864 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2865 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2866 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2867 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2868 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2869 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2870 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2871 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2873 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002874#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2876 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002877#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2879 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2880 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2881 {"quit", Tkapp_Quit, METH_VARARGS},
2882 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2883 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2884 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002885};
2886
Barry Warsawfa701a81997-01-16 00:15:11 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888
Guido van Rossum18468821994-06-20 07:49:28 +00002889/**** Tkapp Type Methods ****/
2890
2891static void
Fred Drake509d79a2000-07-08 04:04:38 +00002892Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002893{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002894 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 /*CHECK_TCL_APPARTMENT;*/
2896 ENTER_TCL
2897 Tcl_DeleteInterp(Tkapp_Interp(self));
2898 LEAVE_TCL
2899 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002900 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002901 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002902}
2903
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002904static PyType_Slot Tkapp_Type_slots[] = {
2905 {Py_tp_dealloc, Tkapp_Dealloc},
2906 {Py_tp_methods, Tkapp_methods},
2907 {0, 0}
2908};
2909
2910
2911static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002912 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002913 sizeof(TkappObject),
2914 0,
2915 Py_TPFLAGS_DEFAULT,
2916 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002917};
2918
Barry Warsawfa701a81997-01-16 00:15:11 +00002919
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920
Guido van Rossum18468821994-06-20 07:49:28 +00002921/**** Tkinter Module ****/
2922
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002923typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002925 Py_ssize_t size; /* current size */
2926 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002927} FlattenContext;
2928
2929static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002930_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 /* expand tuple to hold (at least) size new items.
2933 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002934
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002935 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002938 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002943}
2944
2945static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002946_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002947{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002949
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002950 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 if (depth > 1000) {
2953 PyErr_SetString(PyExc_ValueError,
2954 "nesting too deep in _flatten");
2955 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002956 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2957 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002958 /* preallocate (assume no nesting) */
2959 if (context->size + size > context->maxsize &&
2960 !_bump(context, size))
2961 return 0;
2962 /* copy items to output tuple */
2963 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002964 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002965 if (PyList_Check(o) || PyTuple_Check(o)) {
2966 if (!_flatten1(context, o, depth + 1))
2967 return 0;
2968 } else if (o != Py_None) {
2969 if (context->size + 1 > context->maxsize &&
2970 !_bump(context, 1))
2971 return 0;
2972 Py_INCREF(o);
2973 PyTuple_SET_ITEM(context->tuple,
2974 context->size++, o);
2975 }
2976 }
2977 } else {
2978 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2979 return 0;
2980 }
2981 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002982}
2983
2984static PyObject *
2985Tkinter_Flatten(PyObject* self, PyObject* args)
2986{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002987 FlattenContext context;
2988 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002989
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2991 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002992
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 context.maxsize = PySequence_Size(item);
2994 if (context.maxsize < 0)
2995 return NULL;
2996 if (context.maxsize == 0)
2997 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002998
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002999 context.tuple = PyTuple_New(context.maxsize);
3000 if (!context.tuple)
3001 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003002
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003003 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003004
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005 if (!_flatten1(&context, item,0))
3006 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 if (_PyTuple_Resize(&context.tuple, context.size))
3009 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003011 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003012}
3013
Guido van Rossum18468821994-06-20 07:49:28 +00003014static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003015Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003016{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017 char *screenName = NULL;
3018 char *baseName = NULL; /* XXX this is not used anymore;
3019 try getting rid of it. */
3020 char *className = NULL;
3021 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03003022 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3024 int sync = 0; /* pass -sync to wish */
3025 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003027 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3030 &screenName, &baseName, &className,
3031 &interactive, &wantobjects, &wantTk,
3032 &sync, &use))
3033 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003034 CHECK_STRING_LENGTH(screenName);
3035 CHECK_STRING_LENGTH(baseName);
3036 CHECK_STRING_LENGTH(className);
3037 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003039 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003040 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003042}
3043
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003044static PyObject *
3045Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3046{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 int new_val;
3048 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3049 return NULL;
3050 if (new_val < 0) {
3051 PyErr_SetString(PyExc_ValueError,
3052 "busywaitinterval must be >= 0");
3053 return NULL;
3054 }
3055 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003056 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003057}
3058
3059static char setbusywaitinterval_doc[] =
3060"setbusywaitinterval(n) -> None\n\
3061\n\
3062Set the busy-wait interval in milliseconds between successive\n\
3063calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3064It should be set to a divisor of the maximum time between\n\
3065frames in an animation.";
3066
3067static PyObject *
3068Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3069{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003070 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003071}
3072
3073static char getbusywaitinterval_doc[] =
3074"getbusywaitinterval() -> int\n\
3075\n\
3076Return the current busy-wait interval between successive\n\
3077calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3078
Guido van Rossum18468821994-06-20 07:49:28 +00003079static PyMethodDef moduleMethods[] =
3080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003081 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3082 {"create", Tkinter_Create, METH_VARARGS},
3083 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3084 setbusywaitinterval_doc},
3085 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3086 METH_NOARGS, getbusywaitinterval_doc},
3087 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003088};
3089
Guido van Rossum7bf15641998-05-22 18:28:17 +00003090#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003091
3092static int stdin_ready = 0;
3093
Guido van Rossumad4db171998-06-13 13:56:28 +00003094#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003095static void
Fred Drake509d79a2000-07-08 04:04:38 +00003096MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003099}
Guido van Rossumad4db171998-06-13 13:56:28 +00003100#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003101
Martin v. Löwisa9656492003-03-30 08:44:58 +00003102#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003103static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003104#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003105
Guido van Rossum18468821994-06-20 07:49:28 +00003106static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003107EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003108{
Guido van Rossumad4db171998-06-13 13:56:28 +00003109#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003111#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003112#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003114#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 stdin_ready = 0;
3116 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003117#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 tfile = fileno(stdin);
3119 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003120#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003121 while (!errorInCmd && !stdin_ready) {
3122 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003123#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 if (_kbhit()) {
3125 stdin_ready = 1;
3126 break;
3127 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003128#endif
3129#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 Py_BEGIN_ALLOW_THREADS
3131 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3132 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 tcl_tstate = NULL;
3137 if(tcl_lock)PyThread_release_lock(tcl_lock);
3138 if (result == 0)
3139 Sleep(Tkinter_busywaitinterval);
3140 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003141#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003143#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003145 if (result < 0)
3146 break;
3147 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003148#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003149 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003150#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 if (errorInCmd) {
3152 errorInCmd = 0;
3153 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3154 excInCmd = valInCmd = trbInCmd = NULL;
3155 PyErr_Print();
3156 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003157#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003159#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003160 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003161}
Guido van Rossum18468821994-06-20 07:49:28 +00003162
Guido van Rossum00d93061998-05-28 23:06:38 +00003163#endif
3164
Guido van Rossum7bf15641998-05-22 18:28:17 +00003165static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003166EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003167{
Guido van Rossum00d93061998-05-28 23:06:38 +00003168#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003170#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003171 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003172#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003173 PyOS_InputHook = EventHook;
3174 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003175#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003176}
3177
3178static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003179DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003180{
Guido van Rossum00d93061998-05-28 23:06:38 +00003181#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3183 PyOS_InputHook = NULL;
3184 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003185#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003186}
3187
Barry Warsawfa701a81997-01-16 00:15:11 +00003188
Martin v. Löwis1a214512008-06-11 05:26:20 +00003189static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 PyModuleDef_HEAD_INIT,
3191 "_tkinter",
3192 NULL,
3193 -1,
3194 moduleMethods,
3195 NULL,
3196 NULL,
3197 NULL,
3198 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003199};
3200
Mark Hammond62b1ab12002-07-23 06:31:15 +00003201PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003202PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003203{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003204 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003205
Guido van Rossum00d93061998-05-28 23:06:38 +00003206#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003207 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003208 if (tcl_lock == NULL)
3209 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003210#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003212 m = PyModule_Create(&_tkintermodule);
3213 if (m == NULL)
3214 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003215
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003216 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3217 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003218 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003219 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003220 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003221 Py_INCREF(o);
3222 if (PyModule_AddObject(m, "TclError", o)) {
3223 Py_DECREF(o);
3224 Py_DECREF(m);
3225 return NULL;
3226 }
3227 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003228
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003229 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3230 Py_DECREF(m);
3231 return NULL;
3232 }
3233 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3234 Py_DECREF(m);
3235 return NULL;
3236 }
3237 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3238 Py_DECREF(m);
3239 return NULL;
3240 }
3241 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3242 Py_DECREF(m);
3243 return NULL;
3244 }
3245 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3246 Py_DECREF(m);
3247 return NULL;
3248 }
3249 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3250 Py_DECREF(m);
3251 return NULL;
3252 }
3253 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3254 Py_DECREF(m);
3255 return NULL;
3256 }
3257 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3258 Py_DECREF(m);
3259 return NULL;
3260 }
3261 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3262 Py_DECREF(m);
3263 return NULL;
3264 }
3265 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3266 Py_DECREF(m);
3267 return NULL;
3268 }
3269 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3270 Py_DECREF(m);
3271 return NULL;
3272 }
3273
3274 o = PyType_FromSpec(&Tkapp_Type_spec);
3275 if (o == NULL) {
3276 Py_DECREF(m);
3277 return NULL;
3278 }
3279 if (PyModule_AddObject(m, "TkappType", o)) {
3280 Py_DECREF(o);
3281 Py_DECREF(m);
3282 return NULL;
3283 }
3284 Tkapp_Type = o;
3285
3286 o = PyType_FromSpec(&Tktt_Type_spec);
3287 if (o == NULL) {
3288 Py_DECREF(m);
3289 return NULL;
3290 }
3291 if (PyModule_AddObject(m, "TkttType", o)) {
3292 Py_DECREF(o);
3293 Py_DECREF(m);
3294 return NULL;
3295 }
3296 Tktt_Type = o;
3297
3298 o = PyType_FromSpec(&PyTclObject_Type_spec);
3299 if (o == NULL) {
3300 Py_DECREF(m);
3301 return NULL;
3302 }
3303 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3304 Py_DECREF(o);
3305 Py_DECREF(m);
3306 return NULL;
3307 }
3308 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003309
3310#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003311 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3312 * start waking up. Note that Tcl_FindExecutable will do this, this
3313 * code must be above it! The original warning from
3314 * tkMacOSXAppInit.c is copied below.
3315 *
3316 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3317 * Tcl interpreter for now. It probably should work to do this
3318 * in the other order, but for now it doesn't seem to.
3319 *
3320 */
3321 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003322#endif
3323
3324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003325 /* This helps the dynamic loader; in Unicode aware Tcl versions
3326 it also helps Tcl find its encodings. */
3327 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3328 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003329 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003330 if (cexe)
3331 Tcl_FindExecutable(PyBytes_AsString(cexe));
3332 Py_XDECREF(cexe);
3333 Py_DECREF(uexe);
3334 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003336 if (PyErr_Occurred()) {
3337 Py_DECREF(m);
3338 return NULL;
3339 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003340
Guido van Rossum43ff8681998-07-14 18:02:13 +00003341#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003342 /* This was not a good idea; through <Destroy> bindings,
3343 Tcl_Finalize() may invoke Python code but at that point the
3344 interpreter and thread state have already been destroyed! */
3345 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003346#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003348}