blob: 241c1a0a4d872e5cc545d1f7f98f01ce34e20868 [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 *
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001937Tkapp_GetBoolean(PyObject *self, PyObject *arg)
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
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001942 if (PyLong_Check(arg)) { /* int or bool */
1943 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001944 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001945
1946 if (PyTclObject_Check(arg)) {
1947 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
1948 ((PyTclObject*)arg)->value,
1949 &v) == TCL_ERROR)
1950 return Tkinter_Error(self);
1951 return PyBool_FromLong(v);
1952 }
1953
1954 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001956 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001957 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1958 return Tkinter_Error(self);
1959 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001960}
1961
1962static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001963Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001964{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 char *s;
1966 PyObject *res = NULL;
1967 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001968
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1970 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001971
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001972 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001973 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 ENTER_TCL
1976 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1977 ENTER_OVERLAP
1978 if (retval == TCL_ERROR)
1979 res = Tkinter_Error(self);
1980 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001981 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 LEAVE_OVERLAP_TCL
1983 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001984}
1985
1986static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001987Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 char *s;
1990 PyObject *res = NULL;
1991 int retval;
1992 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1995 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001996
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001997 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 ENTER_TCL
2001 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2002 ENTER_OVERLAP
2003 if (retval == TCL_ERROR)
2004 res = Tkinter_Error(self);
2005 else
2006 res = Py_BuildValue("l", v);
2007 LEAVE_OVERLAP_TCL
2008 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002009}
2010
2011static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002012Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002013{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 char *s;
2015 PyObject *res = NULL;
2016 double v;
2017 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2020 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002021 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022 CHECK_TCL_APPARTMENT;
2023 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2024 ENTER_TCL
2025 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2026 ENTER_OVERLAP
2027 PyFPE_END_PROTECT(retval)
2028 if (retval == TCL_ERROR)
2029 res = Tkinter_Error(self);
2030 else
2031 res = Py_BuildValue("d", v);
2032 LEAVE_OVERLAP_TCL
2033 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002034}
2035
2036static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002037Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002038{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 char *s;
2040 PyObject *res = NULL;
2041 int retval;
2042 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002044 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2045 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002046 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002047 CHECK_TCL_APPARTMENT;
2048 ENTER_TCL
2049 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2050 ENTER_OVERLAP
2051 if (retval == TCL_ERROR)
2052 res = Tkinter_Error(self);
2053 else
2054 res = Py_BuildValue("i", v);
2055 LEAVE_OVERLAP_TCL
2056 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002057}
2058
Barry Warsawfa701a81997-01-16 00:15:11 +00002059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002060
Guido van Rossum18468821994-06-20 07:49:28 +00002061static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002062Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064 char *list;
2065 int argc;
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002066 const char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002067 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002070 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2071 return NULL;
2072 if (PyTclObject_Check(arg)) {
2073 int objc;
2074 Tcl_Obj **objv;
2075 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2076 ((PyTclObject*)arg)->value,
2077 &objc, &objv) == TCL_ERROR) {
2078 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002079 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002080 if (!(v = PyTuple_New(objc)))
2081 return NULL;
2082 for (i = 0; i < objc; i++) {
2083 PyObject *s = FromObj(self, objv[i]);
2084 if (!s || PyTuple_SetItem(v, i, s)) {
2085 Py_DECREF(v);
2086 return NULL;
2087 }
2088 }
2089 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002090 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002091 if (PyTuple_Check(arg)) {
2092 Py_INCREF(arg);
2093 return arg;
2094 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002095 if (PyList_Check(arg)) {
2096 return PySequence_Tuple(arg);
2097 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2100 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002101
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002102 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002103 if (Tcl_SplitList(Tkapp_Interp(self), list,
2104 &argc, &argv) == TCL_ERROR) {
2105 PyMem_Free(list);
2106 return Tkinter_Error(self);
2107 }
Guido van Rossum18468821994-06-20 07:49:28 +00002108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002109 if (!(v = PyTuple_New(argc)))
2110 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002113 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 if (!s || PyTuple_SetItem(v, i, s)) {
2115 Py_DECREF(v);
2116 v = NULL;
2117 goto finally;
2118 }
2119 }
Guido van Rossum18468821994-06-20 07:49:28 +00002120
Barry Warsawfa701a81997-01-16 00:15:11 +00002121 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 ckfree(FREECAST argv);
2123 PyMem_Free(list);
2124 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002125}
2126
2127static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002128Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002129{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002130 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002132
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002133 if (!PyArg_ParseTuple(args, "O:split", &arg))
2134 return NULL;
2135 if (PyTclObject_Check(arg)) {
2136 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2137 int objc;
2138 Tcl_Obj **objv;
2139 int i;
2140 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2141 &objc, &objv) == TCL_ERROR) {
2142 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002143 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002144 if (objc == 0)
2145 return PyUnicode_FromString("");
2146 if (objc == 1)
2147 return FromObj(self, objv[0]);
2148 if (!(v = PyTuple_New(objc)))
2149 return NULL;
2150 for (i = 0; i < objc; i++) {
2151 PyObject *s = FromObj(self, objv[i]);
2152 if (!s || PyTuple_SetItem(v, i, s)) {
2153 Py_DECREF(v);
2154 return NULL;
2155 }
2156 }
2157 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002159 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002160 return SplitObj(arg);
2161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2163 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002164 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 v = Split(list);
2166 PyMem_Free(list);
2167 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002168}
2169
Barry Warsawfa701a81997-01-16 00:15:11 +00002170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171
Guido van Rossum18468821994-06-20 07:49:28 +00002172/** Tcl Command **/
2173
Guido van Rossum00d93061998-05-28 23:06:38 +00002174/* Client data struct */
2175typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 PyObject *self;
2177 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002178} PythonCmd_ClientData;
2179
2180static int
Fred Drake509d79a2000-07-08 04:04:38 +00002181PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 errorInCmd = 1;
2184 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2185 LEAVE_PYTHON
2186 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002187}
2188
Guido van Rossum18468821994-06-20 07:49:28 +00002189/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002190 * function or method.
2191 */
Guido van Rossum18468821994-06-20 07:49:28 +00002192static int
Serhiy Storchaka6716d602014-07-30 19:19:21 +03002193PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002196 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 int i, rv;
2198 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002202 /* TBD: no error checking here since we know, via the
2203 * Tkapp_CreateCommand() that the client data is a two-tuple
2204 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002205 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 /* Create argument list (argv1, ..., argvN) */
2208 if (!(arg = PyTuple_New(argc - 1)))
2209 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002211 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002212 PyObject *s = unicodeFromTclString(argv[i + 1]);
2213 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 Py_DECREF(arg);
2215 return PythonCmd_Error(interp);
2216 }
2217 }
2218 res = PyEval_CallObject(func, arg);
2219 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 if (res == NULL)
2222 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002224 obj_res = AsObj(res);
2225 if (obj_res == NULL) {
2226 Py_DECREF(res);
2227 return PythonCmd_Error(interp);
2228 }
2229 else {
2230 Tcl_SetObjResult(interp, obj_res);
2231 rv = TCL_OK;
2232 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002239}
2240
2241static void
Fred Drake509d79a2000-07-08 04:04:38 +00002242PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002243{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246 ENTER_PYTHON
2247 Py_XDECREF(data->self);
2248 Py_XDECREF(data->func);
2249 PyMem_DEL(data);
2250 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002251}
2252
Barry Warsawfa701a81997-01-16 00:15:11 +00002253
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002254
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002255
Benjamin Peterson5879d412009-03-30 14:51:56 +00002256#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002257TCL_DECLARE_MUTEX(command_mutex)
2258
2259typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002260 Tcl_Event ev;
2261 Tcl_Interp* interp;
2262 char *name;
2263 int create;
2264 int *status;
2265 ClientData *data;
2266 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002267} CommandEvent;
2268
2269static int
2270Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002271{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 if (ev->create)
2273 *ev->status = Tcl_CreateCommand(
2274 ev->interp, ev->name, PythonCmd,
2275 ev->data, PythonCmdDelete) == NULL;
2276 else
2277 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2278 Tcl_MutexLock(&command_mutex);
2279 Tcl_ConditionNotify(ev->done);
2280 Tcl_MutexUnlock(&command_mutex);
2281 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002282}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002283#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002284
2285static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002286Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002288 TkappObject *self = (TkappObject*)selfptr;
2289 PythonCmd_ClientData *data;
2290 char *cmdName;
2291 PyObject *func;
2292 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002293
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2295 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002296 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 if (!PyCallable_Check(func)) {
2298 PyErr_SetString(PyExc_TypeError, "command not callable");
2299 return NULL;
2300 }
Guido van Rossum18468821994-06-20 07:49:28 +00002301
Martin v. Löwisa9656492003-03-30 08:44:58 +00002302#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2304 !WaitForMainloop(self))
2305 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002306#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 data = PyMem_NEW(PythonCmd_ClientData, 1);
2309 if (!data)
2310 return PyErr_NoMemory();
2311 Py_INCREF(self);
2312 Py_INCREF(func);
2313 data->self = selfptr;
2314 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002315#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2317 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002318 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2319 if (ev == NULL) {
2320 PyErr_NoMemory();
2321 PyMem_DEL(data);
2322 return NULL;
2323 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2325 ev->interp = self->interp;
2326 ev->create = 1;
2327 ev->name = cmdName;
2328 ev->data = (ClientData)data;
2329 ev->status = &err;
2330 ev->done = &cond;
2331 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2332 Tcl_ConditionFinalize(&cond);
2333 }
2334 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002335#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 {
2337 ENTER_TCL
2338 err = Tcl_CreateCommand(
2339 Tkapp_Interp(self), cmdName, PythonCmd,
2340 (ClientData)data, PythonCmdDelete) == NULL;
2341 LEAVE_TCL
2342 }
2343 if (err) {
2344 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2345 PyMem_DEL(data);
2346 return NULL;
2347 }
Guido van Rossum18468821994-06-20 07:49:28 +00002348
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002349 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002350}
2351
Barry Warsawfa701a81997-01-16 00:15:11 +00002352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353
Guido van Rossum18468821994-06-20 07:49:28 +00002354static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002355Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002357 TkappObject *self = (TkappObject*)selfptr;
2358 char *cmdName;
2359 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2362 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002363 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002364
2365#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2367 Tcl_Condition cond = NULL;
2368 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002369 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2370 if (ev == NULL) {
2371 PyErr_NoMemory();
2372 return NULL;
2373 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002374 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2375 ev->interp = self->interp;
2376 ev->create = 0;
2377 ev->name = cmdName;
2378 ev->status = &err;
2379 ev->done = &cond;
2380 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2381 &command_mutex);
2382 Tcl_ConditionFinalize(&cond);
2383 }
2384 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002385#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 {
2387 ENTER_TCL
2388 err = Tcl_DeleteCommand(self->interp, cmdName);
2389 LEAVE_TCL
2390 }
2391 if (err == -1) {
2392 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2393 return NULL;
2394 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002395 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002396}
2397
Barry Warsawfa701a81997-01-16 00:15:11 +00002398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399
Guido van Rossum00d93061998-05-28 23:06:38 +00002400#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002401/** File Handler **/
2402
Guido van Rossum00d93061998-05-28 23:06:38 +00002403typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 PyObject *func;
2405 PyObject *file;
2406 int id;
2407 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002408} FileHandler_ClientData;
2409
2410static FileHandler_ClientData *HeadFHCD;
2411
2412static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002413NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 FileHandler_ClientData *p;
2416 p = PyMem_NEW(FileHandler_ClientData, 1);
2417 if (p != NULL) {
2418 Py_XINCREF(func);
2419 Py_XINCREF(file);
2420 p->func = func;
2421 p->file = file;
2422 p->id = id;
2423 p->next = HeadFHCD;
2424 HeadFHCD = p;
2425 }
2426 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002427}
2428
2429static void
Fred Drake509d79a2000-07-08 04:04:38 +00002430DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 pp = &HeadFHCD;
2435 while ((p = *pp) != NULL) {
2436 if (p->id == id) {
2437 *pp = p->next;
2438 Py_XDECREF(p->func);
2439 Py_XDECREF(p->file);
2440 PyMem_DEL(p);
2441 }
2442 else
2443 pp = &p->next;
2444 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002445}
2446
Guido van Rossuma597dde1995-01-10 20:56:29 +00002447static void
Fred Drake509d79a2000-07-08 04:04:38 +00002448FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002449{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2451 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 ENTER_PYTHON
2454 func = data->func;
2455 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 arg = Py_BuildValue("(Oi)", file, (long) mask);
2458 res = PyEval_CallObject(func, arg);
2459 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 if (res == NULL) {
2462 errorInCmd = 1;
2463 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2464 }
2465 Py_XDECREF(res);
2466 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002467}
2468
Guido van Rossum18468821994-06-20 07:49:28 +00002469static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002470Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2471 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002472{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 FileHandler_ClientData *data;
2474 PyObject *file, *func;
2475 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2478 &file, &mask, &func))
2479 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002481 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 tfile = PyObject_AsFileDescriptor(file);
2484 if (tfile < 0)
2485 return NULL;
2486 if (!PyCallable_Check(func)) {
2487 PyErr_SetString(PyExc_TypeError, "bad argument list");
2488 return NULL;
2489 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002491 data = NewFHCD(func, file, tfile);
2492 if (data == NULL)
2493 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 /* Ought to check for null Tcl_File object... */
2496 ENTER_TCL
2497 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2498 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002499 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002500}
2501
2502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002503Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002504{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 PyObject *file;
2506 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2509 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513 tfile = PyObject_AsFileDescriptor(file);
2514 if (tfile < 0)
2515 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519 /* Ought to check for null Tcl_File object... */
2520 ENTER_TCL
2521 Tcl_DeleteFileHandler(tfile);
2522 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002523 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002524}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002525#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002528/**** Tktt Object (timer token) ****/
2529
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002530static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002531
Guido van Rossum00d93061998-05-28 23:06:38 +00002532typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533 PyObject_HEAD
2534 Tcl_TimerToken token;
2535 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002536} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002537
2538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002539Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541 TkttObject *v = (TkttObject *)self;
2542 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002544 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2545 return NULL;
2546 if (v->token != NULL) {
2547 Tcl_DeleteTimerHandler(v->token);
2548 v->token = NULL;
2549 }
2550 if (func != NULL) {
2551 v->func = NULL;
2552 Py_DECREF(func);
2553 Py_DECREF(v); /* See Tktt_New() */
2554 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002555 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002556}
2557
2558static PyMethodDef Tktt_methods[] =
2559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2561 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002562};
2563
2564static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002565Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002568
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002569 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 if (v == NULL)
2571 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002572 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574 Py_INCREF(func);
2575 v->token = NULL;
2576 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578 /* Extra reference, deleted when called or when handler is deleted */
2579 Py_INCREF(v);
2580 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002581}
2582
2583static void
Fred Drake509d79a2000-07-08 04:04:38 +00002584Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002585{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 TkttObject *v = (TkttObject *)self;
2587 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002588 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002589
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002593 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002594}
2595
Guido van Rossum597ac201998-05-12 14:36:19 +00002596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002597Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002600 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2601 v,
2602 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002603}
2604
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002605static PyType_Slot Tktt_Type_slots[] = {
2606 {Py_tp_dealloc, Tktt_Dealloc},
2607 {Py_tp_repr, Tktt_Repr},
2608 {Py_tp_methods, Tktt_methods},
2609 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002610};
2611
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002612static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002613 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002614 sizeof(TkttObject),
2615 0,
2616 Py_TPFLAGS_DEFAULT,
2617 Tktt_Type_slots,
2618};
Barry Warsawfa701a81997-01-16 00:15:11 +00002619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002621/** Timer Handler **/
2622
2623static void
Fred Drake509d79a2000-07-08 04:04:38 +00002624TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002625{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 TkttObject *v = (TkttObject *)clientData;
2627 PyObject *func = v->func;
2628 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 if (func == NULL)
2631 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002635 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 res = PyEval_CallObject(func, NULL);
2638 Py_DECREF(func);
2639 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 if (res == NULL) {
2642 errorInCmd = 1;
2643 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2644 }
2645 else
2646 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002648 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002649}
2650
2651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002652Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002653{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002654 int milliseconds;
2655 PyObject *func;
2656 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2659 &milliseconds, &func))
2660 return NULL;
2661 if (!PyCallable_Check(func)) {
2662 PyErr_SetString(PyExc_TypeError, "bad argument list");
2663 return NULL;
2664 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668 v = Tktt_New(func);
2669 if (v) {
2670 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2671 (ClientData)v);
2672 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002674 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002675}
2676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002677
Guido van Rossum18468821994-06-20 07:49:28 +00002678/** Event Loop **/
2679
Guido van Rossum18468821994-06-20 07:49:28 +00002680static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002681Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 int threshold = 0;
2684 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002685#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002687#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002689 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2690 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692 CHECK_TCL_APPARTMENT;
2693 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 quitMainLoop = 0;
2696 while (Tk_GetNumMainWindows() > threshold &&
2697 !quitMainLoop &&
2698 !errorInCmd)
2699 {
2700 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002701
2702#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002703 if (self->threaded) {
2704 /* Allow other Python threads to run. */
2705 ENTER_TCL
2706 result = Tcl_DoOneEvent(0);
2707 LEAVE_TCL
2708 }
2709 else {
2710 Py_BEGIN_ALLOW_THREADS
2711 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2712 tcl_tstate = tstate;
2713 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2714 tcl_tstate = NULL;
2715 if(tcl_lock)PyThread_release_lock(tcl_lock);
2716 if (result == 0)
2717 Sleep(Tkinter_busywaitinterval);
2718 Py_END_ALLOW_THREADS
2719 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002720#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002721 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002722#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724 if (PyErr_CheckSignals() != 0) {
2725 self->dispatching = 0;
2726 return NULL;
2727 }
2728 if (result < 0)
2729 break;
2730 }
2731 self->dispatching = 0;
2732 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002734 if (errorInCmd) {
2735 errorInCmd = 0;
2736 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2737 excInCmd = valInCmd = trbInCmd = NULL;
2738 return NULL;
2739 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002740 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002741}
2742
2743static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002744Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 int flags = 0;
2747 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002749 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2750 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 ENTER_TCL
2753 rv = Tcl_DoOneEvent(flags);
2754 LEAVE_TCL
2755 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002756}
2757
2758static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002759Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002760{
2761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002762 if (!PyArg_ParseTuple(args, ":quit"))
2763 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002764
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002765 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002766 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002767}
2768
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002769static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002770Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002771{
2772
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002773 if (!PyArg_ParseTuple(args, ":interpaddr"))
2774 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002775
Victor Stinnere1040e22013-09-05 00:22:24 +02002776 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002777}
2778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002780Tkapp_TkInit(PyObject *self, PyObject *args)
2781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002782 Tcl_Interp *interp = Tkapp_Interp(self);
2783 const char * _tk_exists = NULL;
2784 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002785
Guilherme Polob681df42009-02-09 22:33:59 +00002786#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2788 * first call failed.
2789 * To avoid the deadlock, we just refuse the second call through
2790 * a static variable.
2791 */
2792 if (tk_load_failed) {
2793 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2794 return NULL;
2795 }
Guilherme Polob681df42009-02-09 22:33:59 +00002796#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 /* We want to guard against calling Tk_Init() multiple times */
2799 CHECK_TCL_APPARTMENT;
2800 ENTER_TCL
2801 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2802 ENTER_OVERLAP
2803 if (err == TCL_ERROR) {
2804 /* This sets an exception, but we cannot return right
2805 away because we need to exit the overlap first. */
2806 Tkinter_Error(self);
2807 } else {
2808 _tk_exists = Tkapp_Result(self);
2809 }
2810 LEAVE_OVERLAP_TCL
2811 if (err == TCL_ERROR) {
2812 return NULL;
2813 }
2814 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2815 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002816 PyErr_SetString(Tkinter_TclError,
2817 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002818#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002820#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002821 return NULL;
2822 }
2823 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002824 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002825}
Barry Warsawfa701a81997-01-16 00:15:11 +00002826
Martin v. Löwisffad6332002-11-26 09:28:05 +00002827static PyObject *
2828Tkapp_WantObjects(PyObject *self, PyObject *args)
2829{
2830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 int wantobjects = -1;
2832 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2833 return NULL;
2834 if (wantobjects == -1)
2835 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2836 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002837
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002838 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002839}
2840
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002841static PyObject *
2842Tkapp_WillDispatch(PyObject *self, PyObject *args)
2843{
2844
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002845 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002846
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002847 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002848}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850
Guido van Rossum18468821994-06-20 07:49:28 +00002851/**** Tkapp Method List ****/
2852
2853static PyMethodDef Tkapp_methods[] =
2854{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002855 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2856 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2857 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002858 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2860 {"record", Tkapp_Record, METH_VARARGS},
2861 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2862 {"setvar", Tkapp_SetVar, METH_VARARGS},
2863 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2864 {"getvar", Tkapp_GetVar, METH_VARARGS},
2865 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2866 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2867 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2868 {"getint", Tkapp_GetInt, METH_VARARGS},
2869 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002870 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2872 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2873 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2874 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2875 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2876 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002877 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2878 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002879#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2881 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002882#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2884 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2885 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2886 {"quit", Tkapp_Quit, METH_VARARGS},
2887 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2888 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2889 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002890};
2891
Barry Warsawfa701a81997-01-16 00:15:11 +00002892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893
Guido van Rossum18468821994-06-20 07:49:28 +00002894/**** Tkapp Type Methods ****/
2895
2896static void
Fred Drake509d79a2000-07-08 04:04:38 +00002897Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002898{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002899 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 /*CHECK_TCL_APPARTMENT;*/
2901 ENTER_TCL
2902 Tcl_DeleteInterp(Tkapp_Interp(self));
2903 LEAVE_TCL
2904 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002905 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002906 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002907}
2908
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002909static PyType_Slot Tkapp_Type_slots[] = {
2910 {Py_tp_dealloc, Tkapp_Dealloc},
2911 {Py_tp_methods, Tkapp_methods},
2912 {0, 0}
2913};
2914
2915
2916static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002917 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002918 sizeof(TkappObject),
2919 0,
2920 Py_TPFLAGS_DEFAULT,
2921 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002922};
2923
Barry Warsawfa701a81997-01-16 00:15:11 +00002924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925
Guido van Rossum18468821994-06-20 07:49:28 +00002926/**** Tkinter Module ****/
2927
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002928typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 PyObject* tuple;
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002930 Py_ssize_t size; /* current size */
2931 Py_ssize_t maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002932} FlattenContext;
2933
2934static int
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002935_bump(FlattenContext* context, Py_ssize_t size)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002936{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 /* expand tuple to hold (at least) size new items.
2938 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002939
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002940 Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 if (maxsize < context->size + size)
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002943 maxsize = context->size + size; /* never overflows */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002945 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002948}
2949
2950static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002951_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002952{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002953 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002954
Serhiy Storchaka26861b02015-02-16 20:52:17 +02002955 Py_ssize_t i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002956
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002957 if (depth > 1000) {
2958 PyErr_SetString(PyExc_ValueError,
2959 "nesting too deep in _flatten");
2960 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002961 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2962 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 /* preallocate (assume no nesting) */
2964 if (context->size + size > context->maxsize &&
2965 !_bump(context, size))
2966 return 0;
2967 /* copy items to output tuple */
2968 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002969 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 if (PyList_Check(o) || PyTuple_Check(o)) {
2971 if (!_flatten1(context, o, depth + 1))
2972 return 0;
2973 } else if (o != Py_None) {
2974 if (context->size + 1 > context->maxsize &&
2975 !_bump(context, 1))
2976 return 0;
2977 Py_INCREF(o);
2978 PyTuple_SET_ITEM(context->tuple,
2979 context->size++, o);
2980 }
2981 }
2982 } else {
2983 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2984 return 0;
2985 }
2986 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002987}
2988
2989static PyObject *
2990Tkinter_Flatten(PyObject* self, PyObject* args)
2991{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002992 FlattenContext context;
2993 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2996 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 context.maxsize = PySequence_Size(item);
2999 if (context.maxsize < 0)
3000 return NULL;
3001 if (context.maxsize == 0)
3002 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 context.tuple = PyTuple_New(context.maxsize);
3005 if (!context.tuple)
3006 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 if (!_flatten1(&context, item,0))
3011 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003013 if (_PyTuple_Resize(&context.tuple, context.size))
3014 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003017}
3018
Guido van Rossum18468821994-06-20 07:49:28 +00003019static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003020Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003021{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022 char *screenName = NULL;
3023 char *baseName = NULL; /* XXX this is not used anymore;
3024 try getting rid of it. */
3025 char *className = NULL;
3026 int interactive = 0;
Serhiy Storchaka9e7cbda2014-05-28 16:57:55 +03003027 int wantobjects = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003028 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3029 int sync = 0; /* pass -sync to wish */
3030 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003032 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3035 &screenName, &baseName, &className,
3036 &interactive, &wantobjects, &wantTk,
3037 &sync, &use))
3038 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003039 CHECK_STRING_LENGTH(screenName);
3040 CHECK_STRING_LENGTH(baseName);
3041 CHECK_STRING_LENGTH(className);
3042 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003045 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003047}
3048
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003049static PyObject *
3050Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 int new_val;
3053 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3054 return NULL;
3055 if (new_val < 0) {
3056 PyErr_SetString(PyExc_ValueError,
3057 "busywaitinterval must be >= 0");
3058 return NULL;
3059 }
3060 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003061 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003062}
3063
3064static char setbusywaitinterval_doc[] =
3065"setbusywaitinterval(n) -> None\n\
3066\n\
3067Set the busy-wait interval in milliseconds between successive\n\
3068calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3069It should be set to a divisor of the maximum time between\n\
3070frames in an animation.";
3071
3072static PyObject *
3073Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003076}
3077
3078static char getbusywaitinterval_doc[] =
3079"getbusywaitinterval() -> int\n\
3080\n\
3081Return the current busy-wait interval between successive\n\
3082calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3083
Guido van Rossum18468821994-06-20 07:49:28 +00003084static PyMethodDef moduleMethods[] =
3085{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003086 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3087 {"create", Tkinter_Create, METH_VARARGS},
3088 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3089 setbusywaitinterval_doc},
3090 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3091 METH_NOARGS, getbusywaitinterval_doc},
3092 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003093};
3094
Guido van Rossum7bf15641998-05-22 18:28:17 +00003095#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003096
3097static int stdin_ready = 0;
3098
Guido van Rossumad4db171998-06-13 13:56:28 +00003099#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003100static void
Fred Drake509d79a2000-07-08 04:04:38 +00003101MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003102{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003103 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003104}
Guido van Rossumad4db171998-06-13 13:56:28 +00003105#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003106
Martin v. Löwisa9656492003-03-30 08:44:58 +00003107#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003108static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003109#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003110
Guido van Rossum18468821994-06-20 07:49:28 +00003111static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003112EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003113{
Guido van Rossumad4db171998-06-13 13:56:28 +00003114#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003116#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003117#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003119#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 stdin_ready = 0;
3121 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003122#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003123 tfile = fileno(stdin);
3124 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003125#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003126 while (!errorInCmd && !stdin_ready) {
3127 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003128#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 if (_kbhit()) {
3130 stdin_ready = 1;
3131 break;
3132 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003133#endif
3134#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 Py_BEGIN_ALLOW_THREADS
3136 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3137 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 tcl_tstate = NULL;
3142 if(tcl_lock)PyThread_release_lock(tcl_lock);
3143 if (result == 0)
3144 Sleep(Tkinter_busywaitinterval);
3145 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003146#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003148#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003150 if (result < 0)
3151 break;
3152 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003153#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003154 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003155#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003156 if (errorInCmd) {
3157 errorInCmd = 0;
3158 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3159 excInCmd = valInCmd = trbInCmd = NULL;
3160 PyErr_Print();
3161 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003162#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003163 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003164#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003165 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003166}
Guido van Rossum18468821994-06-20 07:49:28 +00003167
Guido van Rossum00d93061998-05-28 23:06:38 +00003168#endif
3169
Guido van Rossum7bf15641998-05-22 18:28:17 +00003170static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003171EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003172{
Guido van Rossum00d93061998-05-28 23:06:38 +00003173#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003174 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003175#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003176 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003177#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003178 PyOS_InputHook = EventHook;
3179 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003180#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003181}
3182
3183static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003184DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003185{
Guido van Rossum00d93061998-05-28 23:06:38 +00003186#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003187 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3188 PyOS_InputHook = NULL;
3189 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003190#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003191}
3192
Barry Warsawfa701a81997-01-16 00:15:11 +00003193
Martin v. Löwis1a214512008-06-11 05:26:20 +00003194static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003195 PyModuleDef_HEAD_INIT,
3196 "_tkinter",
3197 NULL,
3198 -1,
3199 moduleMethods,
3200 NULL,
3201 NULL,
3202 NULL,
3203 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003204};
3205
Mark Hammond62b1ab12002-07-23 06:31:15 +00003206PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003207PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003208{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003209 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003210
Guido van Rossum00d93061998-05-28 23:06:38 +00003211#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003212 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003213 if (tcl_lock == NULL)
3214 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003215#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003217 m = PyModule_Create(&_tkintermodule);
3218 if (m == NULL)
3219 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003220
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003221 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3222 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003223 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003224 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003225 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003226 Py_INCREF(o);
3227 if (PyModule_AddObject(m, "TclError", o)) {
3228 Py_DECREF(o);
3229 Py_DECREF(m);
3230 return NULL;
3231 }
3232 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003234 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3235 Py_DECREF(m);
3236 return NULL;
3237 }
3238 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3239 Py_DECREF(m);
3240 return NULL;
3241 }
3242 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3243 Py_DECREF(m);
3244 return NULL;
3245 }
3246 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3247 Py_DECREF(m);
3248 return NULL;
3249 }
3250 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3251 Py_DECREF(m);
3252 return NULL;
3253 }
3254 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3255 Py_DECREF(m);
3256 return NULL;
3257 }
3258 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3259 Py_DECREF(m);
3260 return NULL;
3261 }
3262 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3263 Py_DECREF(m);
3264 return NULL;
3265 }
3266 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3267 Py_DECREF(m);
3268 return NULL;
3269 }
3270 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3271 Py_DECREF(m);
3272 return NULL;
3273 }
3274 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3275 Py_DECREF(m);
3276 return NULL;
3277 }
3278
3279 o = PyType_FromSpec(&Tkapp_Type_spec);
3280 if (o == NULL) {
3281 Py_DECREF(m);
3282 return NULL;
3283 }
3284 if (PyModule_AddObject(m, "TkappType", o)) {
3285 Py_DECREF(o);
3286 Py_DECREF(m);
3287 return NULL;
3288 }
3289 Tkapp_Type = o;
3290
3291 o = PyType_FromSpec(&Tktt_Type_spec);
3292 if (o == NULL) {
3293 Py_DECREF(m);
3294 return NULL;
3295 }
3296 if (PyModule_AddObject(m, "TkttType", o)) {
3297 Py_DECREF(o);
3298 Py_DECREF(m);
3299 return NULL;
3300 }
3301 Tktt_Type = o;
3302
3303 o = PyType_FromSpec(&PyTclObject_Type_spec);
3304 if (o == NULL) {
3305 Py_DECREF(m);
3306 return NULL;
3307 }
3308 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3309 Py_DECREF(o);
3310 Py_DECREF(m);
3311 return NULL;
3312 }
3313 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003314
3315#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003316 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3317 * start waking up. Note that Tcl_FindExecutable will do this, this
3318 * code must be above it! The original warning from
3319 * tkMacOSXAppInit.c is copied below.
3320 *
3321 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3322 * Tcl interpreter for now. It probably should work to do this
3323 * in the other order, but for now it doesn't seem to.
3324 *
3325 */
3326 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003327#endif
3328
3329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003330 /* This helps the dynamic loader; in Unicode aware Tcl versions
3331 it also helps Tcl find its encodings. */
3332 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3333 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003334 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003335 if (cexe)
3336 Tcl_FindExecutable(PyBytes_AsString(cexe));
3337 Py_XDECREF(cexe);
3338 Py_DECREF(uexe);
3339 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003341 if (PyErr_Occurred()) {
3342 Py_DECREF(m);
3343 return NULL;
3344 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003345
Guido van Rossum43ff8681998-07-14 18:02:13 +00003346#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 /* This was not a good idea; through <Destroy> bindings,
3348 Tcl_Finalize() may invoke Python code but at that point the
3349 interpreter and thread state have already been destroyed! */
3350 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003351#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003352 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003353}