• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
3 
4                         All Rights Reserved
5 
6 ******************************************************************/
7 
8 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
9 
10 /* TCL/TK VERSION INFO:
11 
12     Only Tcl/Tk 8.3.1 and later are supported.  Older versions are not
13     supported. Use Python 2.6 or older if you cannot upgrade your
14     Tcl/Tk libraries.
15 */
16 
17 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
18 
19    - 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 
22 */
23 
24 
25 #include "Python.h"
26 #include <ctype.h>
27 
28 #ifdef WITH_THREAD
29 #include "pythread.h"
30 #endif
31 
32 #ifdef MS_WINDOWS
33 #include <windows.h>
34 #endif
35 
36 /* Allow using this code in Python 2.[12] */
37 #ifndef PyDoc_STRVAR
38 #define PyDoc_STRVAR(name,str) static char name[] = str
39 #endif
40 
41 #ifndef PyMODINIT_FUNC
42 #define PyMODINIT_FUNC void
43 #endif
44 
45 #ifndef PyBool_Check
46 #define PyBool_Check(o)       0
47 #define PyBool_FromLong       PyInt_FromLong
48 #endif
49 
50 #define CHECK_SIZE(size, elemsize) \
51     ((size_t)(size) <= (size_t)INT_MAX && \
52      (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53 
54 /* Starting with Tcl 8.4, many APIs offer const-correctness.  Unfortunately,
55    making _tkinter correct for this API means breaking earlier
56    versions. USE_COMPAT_CONST allows making _tkinter work with both 8.4 and
57    earlier versions. Once Tcl releases before 8.4 don't need to be supported
58    anymore, this should go. */
59 #define USE_COMPAT_CONST
60 
61 /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62    it always; if Tcl is not threaded, the thread functions in
63    Tcl are empty.  */
64 #define TCL_THREADS
65 
66 #ifdef TK_FRAMEWORK
67 #include <Tcl/tcl.h>
68 #include <Tk/tk.h>
69 #else
70 #include <tcl.h>
71 #include <tk.h>
72 #endif
73 
74 #include "tkinter.h"
75 
76 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
77 #ifndef CONST84_RETURN
78 #define CONST84_RETURN
79 #undef CONST
80 #define CONST
81 #endif
82 
83 #if TK_HEX_VERSION < 0x08030201
84 #error "Tk older than 8.3.1 not supported"
85 #endif
86 
87 /* Unicode conversion assumes that Tcl_UniChar is two bytes.
88    We cannot test this directly, so we test UTF-8 size instead,
89    expecting that TCL_UTF_MAX is changed if Tcl ever supports
90    either UTF-16 or UCS-4.
91    Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
92    Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93    as well.
94 */
95 #if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
96 #error "unsupported Tcl configuration"
97 #endif
98 
99 #if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
100     TK_HEX_VERSION >= 0x08060200
101 #define HAVE_LIBTOMMAMTH
102 #include <tclTomMath.h>
103 #endif
104 
105 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
106 #define HAVE_CREATEFILEHANDLER
107 #endif
108 
109 #ifdef HAVE_CREATEFILEHANDLER
110 
111 /* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
112    with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
113 #ifndef TCL_UNIX_FD
114 #  ifdef TCL_WIN_SOCKET
115 #    define TCL_UNIX_FD (! TCL_WIN_SOCKET)
116 #  else
117 #    define TCL_UNIX_FD 1
118 #  endif
119 #endif
120 
121 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
122    messiness.  In Tcl 8.0 and later, it is not available on Windows (and on
123    Unix, only because Jack added it back); when available on Windows, it only
124    applies to sockets. */
125 
126 #ifdef MS_WINDOWS
127 #define FHANDLETYPE TCL_WIN_SOCKET
128 #else
129 #define FHANDLETYPE TCL_UNIX_FD
130 #endif
131 
132 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
133    which uses this to handle Tcl events while the user is typing commands. */
134 
135 #if FHANDLETYPE == TCL_UNIX_FD
136 #define WAIT_FOR_STDIN
137 #endif
138 
139 #endif /* HAVE_CREATEFILEHANDLER */
140 
141 #ifdef MS_WINDOWS
142 #include <conio.h>
143 #define WAIT_FOR_STDIN
144 #endif
145 
146 #ifdef WITH_THREAD
147 
148 /* The threading situation is complicated.  Tcl is not thread-safe, except
149    when configured with --enable-threads.
150    So we need to use a lock around all uses of Tcl.  Previously, the Python
151    interpreter lock was used for this.  However, this causes problems when
152    other Python threads need to run while Tcl is blocked waiting for events.
153 
154    To solve this problem, a separate lock for Tcl is introduced.  Holding it
155    is incompatible with holding Python's interpreter lock.  The following four
156    macros manipulate both locks together.
157 
158    ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
159    Py_END_ALLOW_THREADS.  They should be used whenever a call into Tcl is made
160    that could call an event handler, or otherwise affect the state of a Tcl
161    interpreter.  These assume that the surrounding code has the Python
162    interpreter lock; inside the brackets, the Python interpreter lock has been
163    released and the lock for Tcl has been acquired.
164 
165    Sometimes, it is necessary to have both the Python lock and the Tcl lock.
166    (For example, when transferring data from the Tcl interpreter result to a
167    Python string object.)  This can be done by using different macros to close
168    the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
169    the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
170    releases the Tcl lock.
171 
172    By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
173    handlers when the handler needs to use Python.  Such event handlers are
174    entered while the lock for Tcl is held; the event handler presumably needs
175    to use Python.  ENTER_PYTHON releases the lock for Tcl and acquires
176    the Python interpreter lock, restoring the appropriate thread state, and
177    LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
178    for Tcl.  It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
179    the code between ENTER_PYTHON and LEAVE_PYTHON.
180 
181    These locks expand to several statements and brackets; they should not be
182    used in branches of if statements and the like.
183 
184    If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
185    only valid in the thread that created it, and all Tk activity must happen in this
186    thread, also. That means that the mainloop must be invoked in the thread that
187    created the interpreter. Invoking commands from other threads is possible;
188    _tkinter will queue an event for the interpreter thread, which will then
189    execute the command and pass back the result. If the main thread is not in the
190    mainloop, and invoking commands causes an exception; if the main loop is running
191    but not processing events, the command invocation will block.
192 
193    In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
194    anymore, since multiple Tcl interpreters may simultaneously dispatch in different
195    threads. So we use the Tcl TLS API.
196 
197 */
198 
199 static PyThread_type_lock tcl_lock = 0;
200 
201 #ifdef TCL_THREADS
202 static Tcl_ThreadDataKey state_key;
203 typedef PyThreadState *ThreadSpecificData;
204 #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
205 #else
206 static PyThreadState *tcl_tstate = NULL;
207 #endif
208 
209 #define ENTER_TCL \
210     { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
211         if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
212 
213 #define LEAVE_TCL \
214     tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
215 
216 #define ENTER_OVERLAP \
217     Py_END_ALLOW_THREADS
218 
219 #define LEAVE_OVERLAP_TCL \
220     tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
221 
222 #define ENTER_PYTHON \
223     { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
224         if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
225 
226 #define LEAVE_PYTHON \
227     { PyThreadState *tstate = PyEval_SaveThread(); \
228         if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
229 
230 #define CHECK_TCL_APPARTMENT \
231     if (((TkappObject *)self)->threaded && \
232         ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
233         PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
234         return 0; \
235     }
236 
237 #else
238 
239 #define ENTER_TCL
240 #define LEAVE_TCL
241 #define ENTER_OVERLAP
242 #define LEAVE_OVERLAP_TCL
243 #define ENTER_PYTHON
244 #define LEAVE_PYTHON
245 #define CHECK_TCL_APPARTMENT
246 
247 #endif
248 
249 #ifndef FREECAST
250 #define FREECAST (char *)
251 #endif
252 
253 /**** Tkapp Object Declaration ****/
254 
255 static PyTypeObject Tkapp_Type;
256 
257 typedef struct {
258     PyObject_HEAD
259     Tcl_Interp *interp;
260     int wantobjects;
261     int threaded; /* True if tcl_platform[threaded] */
262     Tcl_ThreadId thread_id;
263     int dispatching;
264     /* We cannot include tclInt.h, as this is internal.
265        So we cache interesting types here. */
266     const Tcl_ObjType *OldBooleanType;
267     const Tcl_ObjType *BooleanType;
268     const Tcl_ObjType *ByteArrayType;
269     const Tcl_ObjType *DoubleType;
270     const Tcl_ObjType *IntType;
271     const Tcl_ObjType *WideIntType;
272     const Tcl_ObjType *BignumType;
273     const Tcl_ObjType *ListType;
274     const Tcl_ObjType *ProcBodyType;
275     const Tcl_ObjType *StringType;
276 } TkappObject;
277 
278 #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
279 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
280 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
281 
282 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
283 (void *) v, Py_REFCNT(v)))
284 
285 
286 
287 /**** Error Handling ****/
288 
289 static PyObject *Tkinter_TclError;
290 static int quitMainLoop = 0;
291 static int errorInCmd = 0;
292 static PyObject *excInCmd;
293 static PyObject *valInCmd;
294 static PyObject *trbInCmd;
295 
296 #ifdef TKINTER_PROTECT_LOADTK
297 static int tk_load_failed;
298 #endif
299 
300 
301 static PyObject *
Tkinter_Error(PyObject * v)302 Tkinter_Error(PyObject *v)
303 {
304     PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
305     return NULL;
306 }
307 
308 
309 
310 /**** Utils ****/
311 
312 static int Tkinter_busywaitinterval = 20;
313 
314 #ifdef WITH_THREAD
315 #ifndef MS_WINDOWS
316 
317 /* Millisecond sleep() for Unix platforms. */
318 
319 static void
Sleep(int milli)320 Sleep(int milli)
321 {
322     /* XXX Too bad if you don't have select(). */
323     struct timeval t;
324     t.tv_sec = milli/1000;
325     t.tv_usec = (milli%1000) * 1000;
326     select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
327 }
328 #endif /* MS_WINDOWS */
329 
330 /* Wait up to 1s for the mainloop to come up. */
331 
332 static int
WaitForMainloop(TkappObject * self)333 WaitForMainloop(TkappObject* self)
334 {
335     int i;
336     for (i = 0; i < 10; i++) {
337         if (self->dispatching)
338             return 1;
339         Py_BEGIN_ALLOW_THREADS
340         Sleep(100);
341         Py_END_ALLOW_THREADS
342     }
343     if (self->dispatching)
344         return 1;
345     PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
346     return 0;
347 }
348 #endif /* WITH_THREAD */
349 
350 
351 static char *
AsString(PyObject * value,PyObject * tmp)352 AsString(PyObject *value, PyObject *tmp)
353 {
354     if (PyString_Check(value))
355         return PyString_AsString(value);
356 #ifdef Py_USING_UNICODE
357     else if (PyUnicode_Check(value)) {
358         PyObject *v = PyUnicode_AsUTF8String(value);
359         if (v == NULL)
360             return NULL;
361         if (PyList_Append(tmp, v) != 0) {
362             Py_DECREF(v);
363             return NULL;
364         }
365         Py_DECREF(v);
366         return PyString_AsString(v);
367     }
368 #endif
369     else {
370         PyObject *v = PyObject_Str(value);
371         if (v == NULL)
372             return NULL;
373         if (PyList_Append(tmp, v) != 0) {
374             Py_DECREF(v);
375             return NULL;
376         }
377         Py_DECREF(v);
378         return PyString_AsString(v);
379     }
380 }
381 
382 
383 
384 #define ARGSZ 64
385 
386 static char *
Merge(PyObject * args)387 Merge(PyObject *args)
388 {
389     PyObject *tmp = NULL;
390     char *argvStore[ARGSZ];
391     char **argv = NULL;
392     int fvStore[ARGSZ];
393     int *fv = NULL;
394     Py_ssize_t argc = 0, fvc = 0, i;
395     char *res = NULL;
396 
397     if (!(tmp = PyList_New(0)))
398         return NULL;
399 
400     argv = argvStore;
401     fv = fvStore;
402 
403     if (args == NULL)
404         argc = 0;
405 
406     else if (!PyTuple_Check(args)) {
407         argc = 1;
408         fv[0] = 0;
409         if (!(argv[0] = AsString(args, tmp)))
410             goto finally;
411     }
412     else {
413         argc = PyTuple_Size(args);
414 
415         if (argc > ARGSZ) {
416             if (!CHECK_SIZE(argc, sizeof(char *))) {
417                 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
418                 goto finally;
419             }
420             argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
421             fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
422             if (argv == NULL || fv == NULL) {
423                 PyErr_NoMemory();
424                 goto finally;
425             }
426         }
427 
428         for (i = 0; i < argc; i++) {
429             PyObject *v = PyTuple_GetItem(args, i);
430             if (PyTuple_Check(v)) {
431                 fv[i] = 1;
432                 if (!(argv[i] = Merge(v)))
433                     goto finally;
434                 fvc++;
435             }
436             else if (v == Py_None) {
437                 argc = i;
438                 break;
439             }
440             else {
441                 fv[i] = 0;
442                 if (!(argv[i] = AsString(v, tmp)))
443                     goto finally;
444                 fvc++;
445             }
446         }
447     }
448     res = Tcl_Merge(argc, argv);
449     if (res == NULL)
450         PyErr_SetString(Tkinter_TclError, "merge failed");
451 
452   finally:
453     for (i = 0; i < fvc; i++)
454         if (fv[i]) {
455             ckfree(argv[i]);
456         }
457     if (argv != argvStore)
458         ckfree(FREECAST argv);
459     if (fv != fvStore)
460         ckfree(FREECAST fv);
461 
462     Py_DECREF(tmp);
463     return res;
464 }
465 
466 
467 
468 #ifdef Py_USING_UNICODE
469 static PyObject *
unicode_FromTclStringAndSize(const char * s,Py_ssize_t size)470 unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
471 {
472     PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
473     if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
474         /* Tcl encodes null character as \xc0\x80 */
475         if (memchr(s, '\xc0', size)) {
476             char *buf, *q;
477             const char *e = s + size;
478             PyErr_Clear();
479             q = buf = (char *)PyMem_Malloc(size);
480             if (buf == NULL) {
481                 PyErr_NoMemory();
482                 return NULL;
483             }
484             while (s != e) {
485                 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
486                     *q++ = '\0';
487                     s += 2;
488                 }
489                 else
490                     *q++ = *s++;
491             }
492             s = buf;
493             size = q - s;
494             r = PyUnicode_DecodeUTF8(s, size, NULL);
495             PyMem_Free(buf);
496         }
497     }
498     return r;
499 }
500 #endif
501 
502 static PyObject *
fromTclStringAndSize(const char * s,Py_ssize_t size)503 fromTclStringAndSize(const char *s, Py_ssize_t size)
504 {
505     PyObject *r;
506 #ifdef Py_USING_UNICODE
507     Py_ssize_t i;
508     /* If Tcl string contains any bytes with the top bit set,
509         it's UTF-8 and we should decode it to Unicode */
510     for (i = 0; i < size; i++)
511         if (s[i] & 0x80)
512             break;
513     if (i != size) {
514         /* It isn't an ASCII string. */
515         r = unicode_FromTclStringAndSize(s, size);
516         if (r)
517             return r;
518         PyErr_Clear();
519     }
520 #endif
521     r = PyString_FromStringAndSize(s, size);
522     return r;
523 }
524 
525 static PyObject *
fromTclString(const char * s)526 fromTclString(const char *s)
527 {
528     return fromTclStringAndSize(s, strlen(s));
529 }
530 
531 
532 static PyObject *
Split(char * list)533 Split(char *list)
534 {
535     int argc;
536     char **argv;
537     PyObject *v;
538 
539     if (list == NULL) {
540         Py_INCREF(Py_None);
541         return Py_None;
542     }
543 
544     if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
545         /* Not a list.
546          * Could be a quoted string containing funnies, e.g. {"}.
547          * Return the string itself.
548          */
549         return PyString_FromString(list);
550     }
551 
552     if (argc == 0)
553         v = PyString_FromString("");
554     else if (argc == 1)
555         v = PyString_FromString(argv[0]);
556     else if ((v = PyTuple_New(argc)) != NULL) {
557         int i;
558         PyObject *w;
559 
560         for (i = 0; i < argc; i++) {
561             if ((w = Split(argv[i])) == NULL) {
562                 Py_DECREF(v);
563                 v = NULL;
564                 break;
565             }
566             PyTuple_SetItem(v, i, w);
567         }
568     }
569     Tcl_Free(FREECAST argv);
570     return v;
571 }
572 
573 /* In some cases, Tcl will still return strings that are supposed to be
574    lists. SplitObj walks through a nested tuple, finding string objects that
575    need to be split. */
576 
577 static PyObject *
SplitObj(PyObject * arg)578 SplitObj(PyObject *arg)
579 {
580     if (PyTuple_Check(arg)) {
581         int i, size;
582         PyObject *elem, *newelem, *result;
583 
584         size = PyTuple_Size(arg);
585         result = NULL;
586         /* Recursively invoke SplitObj for all tuple items.
587            If this does not return a new object, no action is
588            needed. */
589         for(i = 0; i < size; i++) {
590             elem = PyTuple_GetItem(arg, i);
591             newelem = SplitObj(elem);
592             if (!newelem) {
593                 Py_XDECREF(result);
594                 return NULL;
595             }
596             if (!result) {
597                 int k;
598                 if (newelem == elem) {
599                     Py_DECREF(newelem);
600                     continue;
601                 }
602                 result = PyTuple_New(size);
603                 if (!result)
604                     return NULL;
605                 for(k = 0; k < i; k++) {
606                     elem = PyTuple_GetItem(arg, k);
607                     Py_INCREF(elem);
608                     PyTuple_SetItem(result, k, elem);
609                 }
610             }
611             PyTuple_SetItem(result, i, newelem);
612         }
613         if (result)
614             return result;
615         /* Fall through, returning arg. */
616     }
617     else if (PyString_Check(arg)) {
618         int argc;
619         char **argv;
620         char *list = PyString_AsString(arg);
621 
622         if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
623             Py_INCREF(arg);
624             return arg;
625         }
626         Tcl_Free(FREECAST argv);
627         if (argc > 1)
628             return Split(PyString_AsString(arg));
629         /* Fall through, returning arg. */
630     }
631     else if (PyUnicode_Check(arg)) {
632         int argc;
633         char **argv;
634         char *list;
635         PyObject *s = PyUnicode_AsUTF8String(arg);
636 
637         if (s == NULL) {
638             Py_INCREF(arg);
639             return arg;
640         }
641         list = PyString_AsString(s);
642 
643         if (list == NULL ||
644             Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
645             Py_DECREF(s);
646             Py_INCREF(arg);
647             return arg;
648         }
649         Tcl_Free(FREECAST argv);
650         if (argc > 1) {
651             PyObject *v = Split(list);
652             Py_DECREF(s);
653             return v;
654         }
655         Py_DECREF(s);
656         /* Fall through, returning arg. */
657     }
658     Py_INCREF(arg);
659     return arg;
660 }
661 
662 
663 /**** Tkapp Object ****/
664 
665 #ifndef WITH_APPINIT
666 int
Tcl_AppInit(Tcl_Interp * interp)667 Tcl_AppInit(Tcl_Interp *interp)
668 {
669     const char * _tkinter_skip_tk_init;
670 
671     if (Tcl_Init(interp) == TCL_ERROR) {
672         PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
673         return TCL_ERROR;
674     }
675 
676     _tkinter_skip_tk_init = Tcl_GetVar(interp,
677                     "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
678     if (_tkinter_skip_tk_init != NULL &&
679                     strcmp(_tkinter_skip_tk_init, "1") == 0) {
680         return TCL_OK;
681     }
682 
683 #ifdef TKINTER_PROTECT_LOADTK
684     if (tk_load_failed) {
685         PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
686         return TCL_ERROR;
687     }
688 #endif
689 
690     if (Tk_Init(interp) == TCL_ERROR) {
691 #ifdef TKINTER_PROTECT_LOADTK
692         tk_load_failed = 1;
693 #endif
694         PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
695         return TCL_ERROR;
696     }
697 
698     return TCL_OK;
699 }
700 #endif /* !WITH_APPINIT */
701 
702 
703 
704 
705 /* Initialize the Tk application; see the `main' function in
706  * `tkMain.c'.
707  */
708 
709 static void EnableEventHook(void); /* Forward */
710 static void DisableEventHook(void); /* Forward */
711 
712 static TkappObject *
Tkapp_New(char * screenName,char * baseName,char * className,int interactive,int wantobjects,int wantTk,int sync,char * use)713 Tkapp_New(char *screenName, char *baseName, char *className,
714           int interactive, int wantobjects, int wantTk, int sync, char *use)
715 {
716     TkappObject *v;
717     char *argv0;
718 
719     v = PyObject_New(TkappObject, &Tkapp_Type);
720     if (v == NULL)
721         return NULL;
722 
723     v->interp = Tcl_CreateInterp();
724     v->wantobjects = wantobjects;
725     v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
726                                 TCL_GLOBAL_ONLY) != NULL;
727     v->thread_id = Tcl_GetCurrentThread();
728     v->dispatching = 0;
729 
730 #ifndef TCL_THREADS
731     if (v->threaded) {
732         PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
733         Py_DECREF(v);
734         return 0;
735     }
736 #endif
737 #ifdef WITH_THREAD
738     if (v->threaded && tcl_lock) {
739         /* If Tcl is threaded, we don't need the lock. */
740         PyThread_free_lock(tcl_lock);
741         tcl_lock = NULL;
742     }
743 #endif
744 
745     v->OldBooleanType = Tcl_GetObjType("boolean");
746     v->BooleanType = Tcl_GetObjType("booleanString");
747     v->ByteArrayType = Tcl_GetObjType("bytearray");
748     v->DoubleType = Tcl_GetObjType("double");
749     v->IntType = Tcl_GetObjType("int");
750     v->WideIntType = Tcl_GetObjType("wideInt");
751     v->BignumType = Tcl_GetObjType("bignum");
752     v->ListType = Tcl_GetObjType("list");
753     v->ProcBodyType = Tcl_GetObjType("procbody");
754     v->StringType = Tcl_GetObjType("string");
755 
756     /* Delete the 'exit' command, which can screw things up */
757     Tcl_DeleteCommand(v->interp, "exit");
758 
759     if (screenName != NULL)
760         Tcl_SetVar2(v->interp, "env", "DISPLAY",
761                     screenName, TCL_GLOBAL_ONLY);
762 
763     if (interactive)
764         Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
765     else
766         Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
767 
768     /* This is used to get the application class for Tk 4.1 and up */
769     argv0 = (char*)attemptckalloc(strlen(className) + 1);
770     if (!argv0) {
771         PyErr_NoMemory();
772         Py_DECREF(v);
773         return NULL;
774     }
775 
776     strcpy(argv0, className);
777     if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
778         argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
779     Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
780     ckfree(argv0);
781 
782     if (! wantTk) {
783         Tcl_SetVar(v->interp,
784                         "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
785     }
786 #ifdef TKINTER_PROTECT_LOADTK
787     else if (tk_load_failed) {
788         Tcl_SetVar(v->interp,
789                         "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
790     }
791 #endif
792 
793     /* some initial arguments need to be in argv */
794     if (sync || use) {
795         char *args;
796         int len = 0;
797 
798         if (sync)
799             len += sizeof "-sync";
800         if (use)
801             len += strlen(use) + sizeof "-use ";
802 
803         args = (char*)attemptckalloc(len);
804         if (!args) {
805             PyErr_NoMemory();
806             Py_DECREF(v);
807             return NULL;
808         }
809 
810         args[0] = '\0';
811         if (sync)
812             strcat(args, "-sync");
813         if (use) {
814             if (sync)
815                 strcat(args, " ");
816             strcat(args, "-use ");
817             strcat(args, use);
818         }
819 
820         Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
821         ckfree(args);
822     }
823 
824     if (Tcl_AppInit(v->interp) != TCL_OK) {
825         PyObject *result = Tkinter_Error((PyObject *)v);
826 #ifdef TKINTER_PROTECT_LOADTK
827         if (wantTk) {
828             const char *_tkinter_tk_failed;
829             _tkinter_tk_failed = Tcl_GetVar(v->interp,
830                             "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
831 
832             if ( _tkinter_tk_failed != NULL &&
833                             strcmp(_tkinter_tk_failed, "1") == 0) {
834                 tk_load_failed = 1;
835             }
836         }
837 #endif
838         Py_DECREF((PyObject *)v);
839         return (TkappObject *)result;
840     }
841 
842     EnableEventHook();
843 
844     return v;
845 }
846 
847 
848 #ifdef WITH_THREAD
849 static void
Tkapp_ThreadSend(TkappObject * self,Tcl_Event * ev,Tcl_Condition * cond,Tcl_Mutex * mutex)850 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
851                  Tcl_Condition *cond, Tcl_Mutex *mutex)
852 {
853     Py_BEGIN_ALLOW_THREADS;
854     Tcl_MutexLock(mutex);
855     Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
856     Tcl_ThreadAlert(self->thread_id);
857     Tcl_ConditionWait(cond, mutex, NULL);
858     Tcl_MutexUnlock(mutex);
859     Py_END_ALLOW_THREADS
860 }
861 #endif
862 
863 
864 /** Tcl Eval **/
865 
866 typedef struct {
867     PyObject_HEAD
868     Tcl_Obj *value;
869     PyObject *string; /* This cannot cause cycles. */
870 } PyTclObject;
871 
872 staticforward PyTypeObject PyTclObject_Type;
873 #define PyTclObject_Check(v)    ((v)->ob_type == &PyTclObject_Type)
874 
875 static PyObject *
newPyTclObject(Tcl_Obj * arg)876 newPyTclObject(Tcl_Obj *arg)
877 {
878     PyTclObject *self;
879     self = PyObject_New(PyTclObject, &PyTclObject_Type);
880     if (self == NULL)
881         return NULL;
882     Tcl_IncrRefCount(arg);
883     self->value = arg;
884     self->string = NULL;
885     return (PyObject*)self;
886 }
887 
888 static void
PyTclObject_dealloc(PyTclObject * self)889 PyTclObject_dealloc(PyTclObject *self)
890 {
891     Tcl_DecrRefCount(self->value);
892     Py_XDECREF(self->string);
893     PyObject_Del(self);
894 }
895 
896 static PyObject *
PyTclObject_str(PyTclObject * self)897 PyTclObject_str(PyTclObject *self)
898 {
899     if (self->string && PyString_Check(self->string)) {
900         Py_INCREF(self->string);
901         return self->string;
902     }
903     /* XXX Could cache value if it is an ASCII string. */
904     return PyString_FromString(Tcl_GetString(self->value));
905 }
906 
907 static char*
PyTclObject_TclString(PyObject * self)908 PyTclObject_TclString(PyObject *self)
909 {
910     return Tcl_GetString(((PyTclObject*)self)->value);
911 }
912 
913 /* Like _str, but create Unicode if necessary. */
914 PyDoc_STRVAR(PyTclObject_string__doc__,
915 "the string representation of this object, either as string or Unicode");
916 
917 static PyObject *
PyTclObject_string(PyTclObject * self,void * ignored)918 PyTclObject_string(PyTclObject *self, void *ignored)
919 {
920     if (!self->string) {
921         int len;
922         char *s = Tcl_GetStringFromObj(self->value, &len);
923         self->string = fromTclStringAndSize(s, len);
924         if (!self->string)
925             return NULL;
926     }
927     Py_INCREF(self->string);
928     return self->string;
929 }
930 
931 #ifdef Py_USING_UNICODE
932 PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
933 
934 static PyObject *
PyTclObject_unicode(PyTclObject * self,void * ignored)935 PyTclObject_unicode(PyTclObject *self, void *ignored)
936 {
937     char *s;
938     int len;
939     if (self->string && PyUnicode_Check(self->string)) {
940         Py_INCREF(self->string);
941         return self->string;
942     }
943     /* XXX Could chache result if it is non-ASCII. */
944     s = Tcl_GetStringFromObj(self->value, &len);
945     return unicode_FromTclStringAndSize(s, len);
946 }
947 #endif
948 
949 static PyObject *
PyTclObject_repr(PyTclObject * self)950 PyTclObject_repr(PyTclObject *self)
951 {
952     char buf[50];
953     PyOS_snprintf(buf, 50, "<%s object at %p>",
954                   self->value->typePtr->name, self->value);
955     return PyString_FromString(buf);
956 }
957 
958 static int
PyTclObject_cmp(PyTclObject * self,PyTclObject * other)959 PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
960 {
961     int res;
962     res = strcmp(Tcl_GetString(self->value),
963                  Tcl_GetString(other->value));
964     if (res < 0) return -1;
965     if (res > 0) return 1;
966     return 0;
967 }
968 
969 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
970 
971 static PyObject*
get_typename(PyTclObject * obj,void * ignored)972 get_typename(PyTclObject* obj, void* ignored)
973 {
974     return PyString_FromString(obj->value->typePtr->name);
975 }
976 
977 
978 static PyGetSetDef PyTclObject_getsetlist[] = {
979     {"typename", (getter)get_typename, NULL, get_typename__doc__},
980     {"string", (getter)PyTclObject_string, NULL,
981      PyTclObject_string__doc__},
982     {0},
983 };
984 
985 static PyMethodDef PyTclObject_methods[] = {
986 #ifdef Py_USING_UNICODE
987     {"__unicode__",     (PyCFunction)PyTclObject_unicode, METH_NOARGS,
988     PyTclObject_unicode__doc__},
989 #endif
990     {0}
991 };
992 
993 statichere PyTypeObject PyTclObject_Type = {
994     PyObject_HEAD_INIT(NULL)
995     0,                          /*ob_size*/
996     "_tkinter.Tcl_Obj",                 /*tp_name*/
997     sizeof(PyTclObject),        /*tp_basicsize*/
998     0,                          /*tp_itemsize*/
999     /* methods */
1000     (destructor)PyTclObject_dealloc, /*tp_dealloc*/
1001     0,                          /*tp_print*/
1002     0,                          /*tp_getattr*/
1003     0,                          /*tp_setattr*/
1004     (cmpfunc)PyTclObject_cmp,           /*tp_compare*/
1005     (reprfunc)PyTclObject_repr,         /*tp_repr*/
1006     0,                          /*tp_as_number*/
1007     0,                          /*tp_as_sequence*/
1008     0,                          /*tp_as_mapping*/
1009     0,                          /*tp_hash*/
1010     0,                      /*tp_call*/
1011     (reprfunc)PyTclObject_str,        /*tp_str*/
1012     PyObject_GenericGetAttr,/*tp_getattro*/
1013     0,                      /*tp_setattro*/
1014     0,                      /*tp_as_buffer*/
1015     Py_TPFLAGS_DEFAULT,     /*tp_flags*/
1016     0,                      /*tp_doc*/
1017     0,                      /*tp_traverse*/
1018     0,                      /*tp_clear*/
1019     0,                      /*tp_richcompare*/
1020     0,                      /*tp_weaklistoffset*/
1021     0,                      /*tp_iter*/
1022     0,                      /*tp_iternext*/
1023     PyTclObject_methods,    /*tp_methods*/
1024     0,                          /*tp_members*/
1025     PyTclObject_getsetlist, /*tp_getset*/
1026     0,                      /*tp_base*/
1027     0,                      /*tp_dict*/
1028     0,                      /*tp_descr_get*/
1029     0,                      /*tp_descr_set*/
1030     0,                      /*tp_dictoffset*/
1031     0,                      /*tp_init*/
1032     0,                      /*tp_alloc*/
1033     0,                      /*tp_new*/
1034     0,                      /*tp_free*/
1035     0,                      /*tp_is_gc*/
1036 };
1037 
1038 #if PY_SIZE_MAX > INT_MAX
1039 #define CHECK_STRING_LENGTH(s) do {                                     \
1040         if (s != NULL && strlen(s) >= INT_MAX) {                        \
1041             PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1042             return NULL;                                                \
1043         } } while(0)
1044 #else
1045 #define CHECK_STRING_LENGTH(s)
1046 #endif
1047 
1048 #ifdef HAVE_LIBTOMMAMTH
1049 static Tcl_Obj*
asBignumObj(PyObject * value)1050 asBignumObj(PyObject *value)
1051 {
1052     Tcl_Obj *result;
1053     int neg;
1054     PyObject *hexstr;
1055     char *hexchars;
1056     mp_int bigValue;
1057 
1058     neg = Py_SIZE(value) < 0;
1059     hexstr = _PyLong_Format(value, 16, 0, 1);
1060     if (hexstr == NULL)
1061         return NULL;
1062     hexchars = PyString_AsString(hexstr);
1063     if (hexchars == NULL) {
1064         Py_DECREF(hexstr);
1065         return NULL;
1066     }
1067     hexchars += neg + 2; /* skip sign and "0x" */
1068     mp_init(&bigValue);
1069     if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1070         mp_clear(&bigValue);
1071         Py_DECREF(hexstr);
1072         PyErr_NoMemory();
1073         return NULL;
1074     }
1075     Py_DECREF(hexstr);
1076     bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1077     result = Tcl_NewBignumObj(&bigValue);
1078     mp_clear(&bigValue);
1079     if (result == NULL) {
1080         PyErr_NoMemory();
1081         return NULL;
1082     }
1083     return result;
1084 }
1085 #endif
1086 
1087 static Tcl_Obj*
AsObj(PyObject * value)1088 AsObj(PyObject *value)
1089 {
1090     Tcl_Obj *result;
1091 
1092     if (PyString_Check(value))
1093         return Tcl_NewStringObj(PyString_AS_STRING(value),
1094                                 PyString_GET_SIZE(value));
1095 
1096     if (PyBool_Check(value))
1097         return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1098 
1099     if (PyInt_Check(value))
1100         return Tcl_NewLongObj(PyInt_AS_LONG(value));
1101 
1102     if (PyLong_CheckExact(value)) {
1103         int overflow;
1104         long longValue;
1105 #ifdef TCL_WIDE_INT_TYPE
1106         Tcl_WideInt wideValue;
1107 #endif
1108         longValue = PyLong_AsLongAndOverflow(value, &overflow);
1109         if (!overflow) {
1110             return Tcl_NewLongObj(longValue);
1111         }
1112         /* If there is an overflow in the long conversion,
1113            fall through to wideInt handling. */
1114 #ifdef TCL_WIDE_INT_TYPE
1115         if (_PyLong_AsByteArray((PyLongObject *)value,
1116                                 (unsigned char *)(void *)&wideValue,
1117                                 sizeof(wideValue),
1118 #ifdef WORDS_BIGENDIAN
1119                                 0,
1120 #else
1121                                 1,
1122 #endif
1123                                 /* signed */ 1) == 0) {
1124             return Tcl_NewWideIntObj(wideValue);
1125         }
1126         PyErr_Clear();
1127 #endif
1128         /* If there is an overflow in the wideInt conversion,
1129            fall through to bignum handling. */
1130 #ifdef HAVE_LIBTOMMAMTH
1131         return asBignumObj(value);
1132 #endif
1133         /* If there is no wideInt or bignum support,
1134            fall through to default object handling. */
1135     }
1136 
1137     if (PyFloat_Check(value))
1138         return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1139 
1140     if (PyTuple_Check(value)) {
1141         Tcl_Obj **argv;
1142         Py_ssize_t size, i;
1143 
1144         size = PyTuple_Size(value);
1145         if (size == 0)
1146             return Tcl_NewListObj(0, NULL);
1147         if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1148             PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1149             return NULL;
1150         }
1151         argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
1152         if(!argv)
1153           return 0;
1154         for (i = 0; i < size; i++)
1155           argv[i] = AsObj(PyTuple_GetItem(value,i));
1156         result = Tcl_NewListObj(PyTuple_Size(value), argv);
1157         ckfree(FREECAST argv);
1158         return result;
1159     }
1160 
1161 #ifdef Py_USING_UNICODE
1162     if (PyUnicode_Check(value)) {
1163         Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1164         Py_ssize_t size = PyUnicode_GET_SIZE(value);
1165         /* This #ifdef assumes that Tcl uses UCS-2.
1166            See TCL_UTF_MAX test above. */
1167 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
1168         Tcl_UniChar *outbuf = NULL;
1169         Py_ssize_t i;
1170         size_t allocsize;
1171         if (size == 0)
1172             return Tcl_NewUnicodeObj((const void *)"", 0);
1173         if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1174             PyErr_SetString(PyExc_OverflowError, "string is too long");
1175             return NULL;
1176         }
1177         if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1178             return Tcl_NewUnicodeObj(inbuf, size);
1179         allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
1180         if (allocsize >= size)
1181             outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
1182         /* Else overflow occurred, and we take the next exit */
1183         if (!outbuf) {
1184             PyErr_NoMemory();
1185             return NULL;
1186         }
1187         for (i = 0; i < size; i++) {
1188             if (inbuf[i] >= 0x10000) {
1189                 /* Tcl doesn't do UTF-16, yet. */
1190                 PyErr_Format(Tkinter_TclError,
1191                              "character U+%x is above the range "
1192                              "(U+0000-U+FFFF) allowed by Tcl",
1193                              (int)inbuf[i]);
1194                 ckfree(FREECAST outbuf);
1195                 return NULL;
1196             }
1197             outbuf[i] = inbuf[i];
1198         }
1199         result = Tcl_NewUnicodeObj(outbuf, size);
1200         ckfree(FREECAST outbuf);
1201         return result;
1202 #else
1203         return Tcl_NewUnicodeObj(inbuf, size);
1204 #endif
1205     }
1206 #endif
1207 
1208     if(PyTclObject_Check(value)) {
1209         Tcl_Obj *v = ((PyTclObject*)value)->value;
1210         Tcl_IncrRefCount(v);
1211         return v;
1212     }
1213 
1214     {
1215         PyObject *v = PyObject_Str(value);
1216         if (!v)
1217             return 0;
1218         result = AsObj(v);
1219         Py_DECREF(v);
1220         return result;
1221     }
1222 }
1223 
1224 static PyObject *
fromBoolean(PyObject * tkapp,Tcl_Obj * value)1225 fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1226 {
1227     int boolValue;
1228     if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1229         return Tkinter_Error(tkapp);
1230     return PyBool_FromLong(boolValue);
1231 }
1232 
1233 #ifdef TCL_WIDE_INT_TYPE
1234 static PyObject*
fromWideIntObj(PyObject * tkapp,Tcl_Obj * value)1235 fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1236 {
1237         Tcl_WideInt wideValue;
1238         if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1239 #ifdef HAVE_LONG_LONG
1240             if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1241                 return PyLong_FromLongLong(wideValue);
1242 #endif
1243             return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1244                                          sizeof(wideValue),
1245 #ifdef WORDS_BIGENDIAN
1246                                          0,
1247 #else
1248                                          1,
1249 #endif
1250                                          /* signed */ 1);
1251         }
1252         return NULL;
1253 }
1254 #endif
1255 
1256 #ifdef HAVE_LIBTOMMAMTH
1257 static PyObject*
fromBignumObj(PyObject * tkapp,Tcl_Obj * value)1258 fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1259 {
1260     mp_int bigValue;
1261     unsigned long numBytes;
1262     unsigned char *bytes;
1263     PyObject *res;
1264 
1265     if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1266         return Tkinter_Error(tkapp);
1267     numBytes = mp_unsigned_bin_size(&bigValue);
1268     bytes = PyMem_Malloc(numBytes);
1269     if (bytes == NULL) {
1270         mp_clear(&bigValue);
1271         return PyErr_NoMemory();
1272     }
1273     if (mp_to_unsigned_bin_n(&bigValue, bytes,
1274                                 &numBytes) != MP_OKAY) {
1275         mp_clear(&bigValue);
1276         PyMem_Free(bytes);
1277         return PyErr_NoMemory();
1278     }
1279     res = _PyLong_FromByteArray(bytes, numBytes,
1280                                 /* big-endian */ 0,
1281                                 /* unsigned */ 0);
1282     PyMem_Free(bytes);
1283     if (res != NULL && bigValue.sign == MP_NEG) {
1284         PyObject *res2 = PyNumber_Negative(res);
1285         Py_DECREF(res);
1286         res = res2;
1287     }
1288     mp_clear(&bigValue);
1289     return res;
1290 }
1291 #endif
1292 
1293 static PyObject*
FromObj(PyObject * tkapp,Tcl_Obj * value)1294 FromObj(PyObject* tkapp, Tcl_Obj *value)
1295 {
1296     PyObject *result = NULL;
1297     TkappObject *app = (TkappObject*)tkapp;
1298     Tcl_Interp *interp = Tkapp_Interp(tkapp);
1299 
1300     if (value->typePtr == NULL) {
1301         result = fromTclStringAndSize(value->bytes, value->length);
1302         return result;
1303     }
1304 
1305     if (value->typePtr == app->BooleanType ||
1306         value->typePtr == app->OldBooleanType) {
1307         return fromBoolean(tkapp, value);
1308     }
1309 
1310     if (value->typePtr == app->ByteArrayType) {
1311         int size;
1312         char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1313         return PyString_FromStringAndSize(data, size);
1314     }
1315 
1316     if (value->typePtr == app->DoubleType) {
1317         return PyFloat_FromDouble(value->internalRep.doubleValue);
1318     }
1319 
1320     if (value->typePtr == app->IntType) {
1321         long longValue;
1322         if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1323             return PyInt_FromLong(longValue);
1324         /* If there is an error in the long conversion,
1325            fall through to wideInt handling. */
1326     }
1327 
1328 #ifdef TCL_WIDE_INT_TYPE
1329     if (value->typePtr == app->IntType ||
1330         value->typePtr == app->WideIntType) {
1331         result = fromWideIntObj(tkapp, value);
1332         if (result != NULL || PyErr_Occurred())
1333             return result;
1334         Tcl_ResetResult(interp);
1335         /* If there is an error in the wideInt conversion,
1336            fall through to bignum handling. */
1337     }
1338 #endif
1339 
1340 #ifdef HAVE_LIBTOMMAMTH
1341     if (value->typePtr == app->IntType ||
1342         value->typePtr == app->WideIntType ||
1343         value->typePtr == app->BignumType) {
1344         return fromBignumObj(tkapp, value);
1345     }
1346 #endif
1347 
1348     if (value->typePtr == app->ListType) {
1349         int size;
1350         int i, status;
1351         PyObject *elem;
1352         Tcl_Obj *tcl_elem;
1353 
1354         status = Tcl_ListObjLength(interp, value, &size);
1355         if (status == TCL_ERROR)
1356             return Tkinter_Error(tkapp);
1357         result = PyTuple_New(size);
1358         if (!result)
1359             return NULL;
1360         for (i = 0; i < size; i++) {
1361             status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
1362             if (status == TCL_ERROR) {
1363                 Py_DECREF(result);
1364                 return Tkinter_Error(tkapp);
1365             }
1366             elem = FromObj(tkapp, tcl_elem);
1367             if (!elem) {
1368                 Py_DECREF(result);
1369                 return NULL;
1370             }
1371             PyTuple_SetItem(result, i, elem);
1372         }
1373         return result;
1374     }
1375 
1376     if (value->typePtr == app->ProcBodyType) {
1377       /* fall through: return tcl object. */
1378     }
1379 
1380     if (value->typePtr == app->StringType) {
1381 #ifdef Py_USING_UNICODE
1382 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1383         PyObject *result;
1384         int size;
1385         Tcl_UniChar *input;
1386         Py_UNICODE *output;
1387 
1388         size = Tcl_GetCharLength(value);
1389         result = PyUnicode_FromUnicode(NULL, size);
1390         if (!result)
1391             return NULL;
1392         input = Tcl_GetUnicode(value);
1393         output = PyUnicode_AS_UNICODE(result);
1394         while (size--)
1395             *output++ = *input++;
1396         return result;
1397 #else
1398         return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1399                                      Tcl_GetCharLength(value));
1400 #endif
1401 #else
1402         int size;
1403         char *c;
1404         c = Tcl_GetStringFromObj(value, &size);
1405         return PyString_FromStringAndSize(c, size);
1406 #endif
1407     }
1408 
1409 #if TK_HEX_VERSION >= 0x08050000
1410     if (app->BooleanType == NULL &&
1411         strcmp(value->typePtr->name, "booleanString") == 0) {
1412         /* booleanString type is not registered in Tcl */
1413         app->BooleanType = value->typePtr;
1414         return fromBoolean(tkapp, value);
1415     }
1416 #endif
1417 
1418 #ifdef HAVE_LIBTOMMAMTH
1419     if (app->BignumType == NULL &&
1420         strcmp(value->typePtr->name, "bignum") == 0) {
1421         /* bignum type is not registered in Tcl */
1422         app->BignumType = value->typePtr;
1423         return fromBignumObj(tkapp, value);
1424     }
1425 #endif
1426 
1427     return newPyTclObject(value);
1428 }
1429 
1430 #ifdef WITH_THREAD
1431 /* This mutex synchronizes inter-thread command calls. */
1432 TCL_DECLARE_MUTEX(call_mutex)
1433 
1434 typedef struct Tkapp_CallEvent {
1435     Tcl_Event ev;            /* Must be first */
1436     TkappObject *self;
1437     PyObject *args;
1438     int flags;
1439     PyObject **res;
1440     PyObject **exc_type, **exc_value, **exc_tb;
1441     Tcl_Condition *done;
1442 } Tkapp_CallEvent;
1443 #endif
1444 
1445 void
Tkapp_CallDeallocArgs(Tcl_Obj ** objv,Tcl_Obj ** objStore,int objc)1446 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1447 {
1448     int i;
1449     for (i = 0; i < objc; i++)
1450         Tcl_DecrRefCount(objv[i]);
1451     if (objv != objStore)
1452         ckfree(FREECAST objv);
1453 }
1454 
1455 /* Convert Python objects to Tcl objects. This must happen in the
1456    interpreter thread, which may or may not be the calling thread. */
1457 
1458 static Tcl_Obj**
Tkapp_CallArgs(PyObject * args,Tcl_Obj ** objStore,int * pobjc)1459 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1460 {
1461     Tcl_Obj **objv = objStore;
1462     Py_ssize_t objc = 0, i;
1463     if (args == NULL)
1464         /* do nothing */;
1465 
1466     else if (!PyTuple_Check(args)) {
1467         objv[0] = AsObj(args);
1468         if (objv[0] == 0)
1469             goto finally;
1470         objc = 1;
1471         Tcl_IncrRefCount(objv[0]);
1472     }
1473     else {
1474         objc = PyTuple_Size(args);
1475 
1476         if (objc > ARGSZ) {
1477             if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1478                 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1479                 return NULL;
1480             }
1481             objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
1482             if (objv == NULL) {
1483                 PyErr_NoMemory();
1484                 objc = 0;
1485                 goto finally;
1486             }
1487         }
1488 
1489         for (i = 0; i < objc; i++) {
1490             PyObject *v = PyTuple_GetItem(args, i);
1491             if (v == Py_None) {
1492                 objc = i;
1493                 break;
1494             }
1495             objv[i] = AsObj(v);
1496             if (!objv[i]) {
1497                 /* Reset objc, so it attempts to clear
1498                    objects only up to i. */
1499                 objc = i;
1500                 goto finally;
1501             }
1502             Tcl_IncrRefCount(objv[i]);
1503         }
1504     }
1505     *pobjc = objc;
1506     return objv;
1507 finally:
1508     Tkapp_CallDeallocArgs(objv, objStore, objc);
1509     return NULL;
1510 }
1511 
1512 /* Convert the results of a command call into a Python objects. */
1513 
1514 static PyObject*
Tkapp_CallResult(TkappObject * self)1515 Tkapp_CallResult(TkappObject *self)
1516 {
1517     PyObject *res = NULL;
1518     Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1519     if(self->wantobjects) {
1520         /* Not sure whether the IncrRef is necessary, but something
1521            may overwrite the interpreter result while we are
1522            converting it. */
1523         Tcl_IncrRefCount(value);
1524         res = FromObj((PyObject*)self, value);
1525         Tcl_DecrRefCount(value);
1526     } else {
1527         int len;
1528         const char *s = Tcl_GetStringFromObj(value, &len);
1529         res = fromTclStringAndSize(s, len);
1530     }
1531     return res;
1532 }
1533 
1534 #ifdef WITH_THREAD
1535 
1536 /* Tkapp_CallProc is the event procedure that is executed in the context of
1537    the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1538    hold the Python lock. */
1539 
1540 static int
Tkapp_CallProc(Tkapp_CallEvent * e,int flags)1541 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1542 {
1543     Tcl_Obj *objStore[ARGSZ];
1544     Tcl_Obj **objv;
1545     int objc;
1546     int i;
1547     ENTER_PYTHON
1548     objv = Tkapp_CallArgs(e->args, objStore, &objc);
1549     if (!objv) {
1550         PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1551         *(e->res) = NULL;
1552     }
1553     LEAVE_PYTHON
1554     if (!objv)
1555         goto done;
1556     i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1557     ENTER_PYTHON
1558     if (i == TCL_ERROR) {
1559         *(e->res) = NULL;
1560         *(e->exc_type) = NULL;
1561         *(e->exc_tb) = NULL;
1562         *(e->exc_value) = PyObject_CallFunction(
1563             Tkinter_TclError, "s",
1564             Tcl_GetStringResult(e->self->interp));
1565     }
1566     else {
1567         *(e->res) = Tkapp_CallResult(e->self);
1568     }
1569     LEAVE_PYTHON
1570 
1571     Tkapp_CallDeallocArgs(objv, objStore, objc);
1572 done:
1573     /* Wake up calling thread. */
1574     Tcl_MutexLock(&call_mutex);
1575     Tcl_ConditionNotify(e->done);
1576     Tcl_MutexUnlock(&call_mutex);
1577     return 1;
1578 }
1579 
1580 #endif
1581 
1582 /* This is the main entry point for calling a Tcl command.
1583    It supports three cases, with regard to threading:
1584    1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1585       the context of the calling thread.
1586    2. Tcl is threaded, caller of the command is in the interpreter thread:
1587       Execute the command in the calling thread. Since the Tcl lock will
1588       not be used, we can merge that with case 1.
1589    3. Tcl is threaded, caller is in a different thread: Must queue an event to
1590       the interpreter thread. Allocation of Tcl objects needs to occur in the
1591       interpreter thread, so we ship the PyObject* args to the target thread,
1592       and perform processing there. */
1593 
1594 static PyObject *
Tkapp_Call(PyObject * selfptr,PyObject * args)1595 Tkapp_Call(PyObject *selfptr, PyObject *args)
1596 {
1597     Tcl_Obj *objStore[ARGSZ];
1598     Tcl_Obj **objv = NULL;
1599     int objc, i;
1600     PyObject *res = NULL;
1601     TkappObject *self = (TkappObject*)selfptr;
1602     int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1603 
1604     /* If args is a single tuple, replace with contents of tuple */
1605     if (1 == PyTuple_Size(args)){
1606         PyObject* item = PyTuple_GetItem(args, 0);
1607         if (PyTuple_Check(item))
1608             args = item;
1609     }
1610 #ifdef WITH_THREAD
1611     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1612         /* We cannot call the command directly. Instead, we must
1613            marshal the parameters to the interpreter thread. */
1614         Tkapp_CallEvent *ev;
1615         Tcl_Condition cond = NULL;
1616         PyObject *exc_type, *exc_value, *exc_tb;
1617         if (!WaitForMainloop(self))
1618             return NULL;
1619         ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1620         if (ev == NULL) {
1621             PyErr_NoMemory();
1622             return NULL;
1623         }
1624         ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1625         ev->self = self;
1626         ev->args = args;
1627         ev->res = &res;
1628         ev->exc_type = &exc_type;
1629         ev->exc_value = &exc_value;
1630         ev->exc_tb = &exc_tb;
1631         ev->done = &cond;
1632 
1633         Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1634 
1635         if (res == NULL) {
1636             if (exc_type)
1637                 PyErr_Restore(exc_type, exc_value, exc_tb);
1638             else
1639                 PyErr_SetObject(Tkinter_TclError, exc_value);
1640         }
1641         Tcl_ConditionFinalize(&cond);
1642     }
1643     else
1644 #endif
1645     {
1646 
1647         objv = Tkapp_CallArgs(args, objStore, &objc);
1648         if (!objv)
1649             return NULL;
1650 
1651         ENTER_TCL
1652 
1653         i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1654 
1655         ENTER_OVERLAP
1656 
1657         if (i == TCL_ERROR)
1658             Tkinter_Error(selfptr);
1659         else
1660             res = Tkapp_CallResult(self);
1661 
1662         LEAVE_OVERLAP_TCL
1663 
1664         Tkapp_CallDeallocArgs(objv, objStore, objc);
1665     }
1666     return res;
1667 }
1668 
1669 
1670 static PyObject *
Tkapp_GlobalCall(PyObject * self,PyObject * args)1671 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1672 {
1673     /* Could do the same here as for Tkapp_Call(), but this is not used
1674        much, so I can't be bothered.  Unfortunately Tcl doesn't export a
1675        way for the user to do what all its Global* variants do (save and
1676        reset the scope pointer, call the local version, restore the saved
1677        scope pointer). */
1678 
1679     char *cmd;
1680     PyObject *res = NULL;
1681 
1682     CHECK_TCL_APPARTMENT;
1683 
1684     cmd  = Merge(args);
1685     if (cmd) {
1686         int err;
1687         ENTER_TCL
1688         err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1689         ENTER_OVERLAP
1690         if (err == TCL_ERROR)
1691             res = Tkinter_Error(self);
1692         else
1693             res = PyString_FromString(Tkapp_Result(self));
1694         LEAVE_OVERLAP_TCL
1695         ckfree(cmd);
1696     }
1697 
1698     return res;
1699 }
1700 
1701 static PyObject *
Tkapp_Eval(PyObject * self,PyObject * args)1702 Tkapp_Eval(PyObject *self, PyObject *args)
1703 {
1704     char *script;
1705     PyObject *res = NULL;
1706     int err;
1707 
1708     if (!PyArg_ParseTuple(args, "s:eval", &script))
1709         return NULL;
1710 
1711     CHECK_STRING_LENGTH(script);
1712     CHECK_TCL_APPARTMENT;
1713 
1714     ENTER_TCL
1715     err = Tcl_Eval(Tkapp_Interp(self), script);
1716     ENTER_OVERLAP
1717     if (err == TCL_ERROR)
1718         res = Tkinter_Error(self);
1719     else
1720         res = PyString_FromString(Tkapp_Result(self));
1721     LEAVE_OVERLAP_TCL
1722     return res;
1723 }
1724 
1725 static PyObject *
Tkapp_GlobalEval(PyObject * self,PyObject * args)1726 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1727 {
1728     char *script;
1729     PyObject *res = NULL;
1730     int err;
1731 
1732     if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1733         return NULL;
1734 
1735     CHECK_TCL_APPARTMENT;
1736 
1737     ENTER_TCL
1738     err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1739     ENTER_OVERLAP
1740     if (err == TCL_ERROR)
1741         res = Tkinter_Error(self);
1742     else
1743         res = PyString_FromString(Tkapp_Result(self));
1744     LEAVE_OVERLAP_TCL
1745     return res;
1746 }
1747 
1748 static PyObject *
Tkapp_EvalFile(PyObject * self,PyObject * args)1749 Tkapp_EvalFile(PyObject *self, PyObject *args)
1750 {
1751     char *fileName;
1752     PyObject *res = NULL;
1753     int err;
1754 
1755     if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1756         return NULL;
1757 
1758     CHECK_STRING_LENGTH(fileName);
1759     CHECK_TCL_APPARTMENT;
1760 
1761     ENTER_TCL
1762     err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1763     ENTER_OVERLAP
1764     if (err == TCL_ERROR)
1765         res = Tkinter_Error(self);
1766 
1767     else
1768         res = PyString_FromString(Tkapp_Result(self));
1769     LEAVE_OVERLAP_TCL
1770     return res;
1771 }
1772 
1773 static PyObject *
Tkapp_Record(PyObject * self,PyObject * args)1774 Tkapp_Record(PyObject *self, PyObject *args)
1775 {
1776     char *script;
1777     PyObject *res = NULL;
1778     int err;
1779 
1780     if (!PyArg_ParseTuple(args, "s:record", &script))
1781         return NULL;
1782 
1783     CHECK_STRING_LENGTH(script);
1784     CHECK_TCL_APPARTMENT;
1785 
1786     ENTER_TCL
1787     err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1788     ENTER_OVERLAP
1789     if (err == TCL_ERROR)
1790         res = Tkinter_Error(self);
1791     else
1792         res = PyString_FromString(Tkapp_Result(self));
1793     LEAVE_OVERLAP_TCL
1794     return res;
1795 }
1796 
1797 static PyObject *
Tkapp_AddErrorInfo(PyObject * self,PyObject * args)1798 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1799 {
1800     char *msg;
1801 
1802     if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1803         return NULL;
1804     CHECK_STRING_LENGTH(msg);
1805     CHECK_TCL_APPARTMENT;
1806 
1807     ENTER_TCL
1808     Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1809     LEAVE_TCL
1810 
1811     Py_INCREF(Py_None);
1812     return Py_None;
1813 }
1814 
1815 
1816 
1817 /** Tcl Variable **/
1818 
1819 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1820 
1821 #ifdef WITH_THREAD
1822 TCL_DECLARE_MUTEX(var_mutex)
1823 
1824 typedef struct VarEvent {
1825     Tcl_Event ev; /* must be first */
1826     PyObject *self;
1827     PyObject *args;
1828     int flags;
1829     EventFunc func;
1830     PyObject **res;
1831     PyObject **exc_type;
1832     PyObject **exc_val;
1833     Tcl_Condition *cond;
1834 } VarEvent;
1835 #endif
1836 
1837 static int
varname_converter(PyObject * in,void * _out)1838 varname_converter(PyObject *in, void *_out)
1839 {
1840     char *s;
1841     char **out = (char**)_out;
1842     if (PyString_Check(in)) {
1843         if (PyString_Size(in) > INT_MAX) {
1844             PyErr_SetString(PyExc_OverflowError, "string is too long");
1845             return 0;
1846         }
1847         s = PyString_AsString(in);
1848         if (strlen(s) != PyString_Size(in)) {
1849             PyErr_SetString(PyExc_ValueError, "null character in string");
1850             return 0;
1851         }
1852         *out = s;
1853         return 1;
1854     }
1855     if (PyTclObject_Check(in)) {
1856         *out = PyTclObject_TclString(in);
1857         return 1;
1858     }
1859     PyErr_Format(PyExc_TypeError,
1860                  "must be str or Tcl_Obj, not %.50s",
1861                  in->ob_type->tp_name);
1862     return 0;
1863 }
1864 
1865 #ifdef WITH_THREAD
1866 
1867 static void
var_perform(VarEvent * ev)1868 var_perform(VarEvent *ev)
1869 {
1870     *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1871     if (!*(ev->res)) {
1872         PyObject *exc, *val, *tb;
1873         PyErr_Fetch(&exc, &val, &tb);
1874         PyErr_NormalizeException(&exc, &val, &tb);
1875         *(ev->exc_type) = exc;
1876         *(ev->exc_val) = val;
1877         Py_XDECREF(tb);
1878     }
1879 
1880 }
1881 
1882 static int
var_proc(VarEvent * ev,int flags)1883 var_proc(VarEvent* ev, int flags)
1884 {
1885     ENTER_PYTHON
1886     var_perform(ev);
1887     Tcl_MutexLock(&var_mutex);
1888     Tcl_ConditionNotify(ev->cond);
1889     Tcl_MutexUnlock(&var_mutex);
1890     LEAVE_PYTHON
1891     return 1;
1892 }
1893 
1894 #endif
1895 
1896 static PyObject*
var_invoke(EventFunc func,PyObject * selfptr,PyObject * args,int flags)1897 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1898 {
1899 #ifdef WITH_THREAD
1900     TkappObject *self = (TkappObject*)selfptr;
1901     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1902         TkappObject *self = (TkappObject*)selfptr;
1903         VarEvent *ev;
1904         PyObject *res, *exc_type, *exc_val;
1905         Tcl_Condition cond = NULL;
1906 
1907         /* The current thread is not the interpreter thread.  Marshal
1908            the call to the interpreter thread, then wait for
1909            completion. */
1910         if (!WaitForMainloop(self))
1911             return NULL;
1912 
1913         ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1914         if (ev == NULL) {
1915             PyErr_NoMemory();
1916             return NULL;
1917         }
1918         ev->self = selfptr;
1919         ev->args = args;
1920         ev->flags = flags;
1921         ev->func = func;
1922         ev->res = &res;
1923         ev->exc_type = &exc_type;
1924         ev->exc_val = &exc_val;
1925         ev->cond = &cond;
1926         ev->ev.proc = (Tcl_EventProc*)var_proc;
1927         Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1928         Tcl_ConditionFinalize(&cond);
1929         if (!res) {
1930             PyErr_SetObject(exc_type, exc_val);
1931             Py_DECREF(exc_type);
1932             Py_DECREF(exc_val);
1933             return NULL;
1934         }
1935         return res;
1936     }
1937 #endif
1938     /* Tcl is not threaded, or this is the interpreter thread. */
1939     return func(selfptr, args, flags);
1940 }
1941 
1942 static PyObject *
SetVar(PyObject * self,PyObject * args,int flags)1943 SetVar(PyObject *self, PyObject *args, int flags)
1944 {
1945     char *name1, *name2;
1946     PyObject *newValue;
1947     PyObject *res = NULL;
1948     Tcl_Obj *newval, *ok;
1949 
1950     switch (PyTuple_GET_SIZE(args)) {
1951     case 2:
1952         if (!PyArg_ParseTuple(args, "O&O:setvar",
1953                               varname_converter, &name1, &newValue))
1954             return NULL;
1955         /* XXX Acquire tcl lock??? */
1956         newval = AsObj(newValue);
1957         if (newval == NULL)
1958             return NULL;
1959         ENTER_TCL
1960         ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1961                            newval, flags);
1962         ENTER_OVERLAP
1963         if (!ok)
1964             Tkinter_Error(self);
1965         else {
1966             res = Py_None;
1967             Py_INCREF(res);
1968         }
1969         LEAVE_OVERLAP_TCL
1970         break;
1971     case 3:
1972         if (!PyArg_ParseTuple(args, "ssO:setvar",
1973                               &name1, &name2, &newValue))
1974             return NULL;
1975         CHECK_STRING_LENGTH(name1);
1976         CHECK_STRING_LENGTH(name2);
1977         /* XXX must hold tcl lock already??? */
1978         newval = AsObj(newValue);
1979         ENTER_TCL
1980         ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1981         ENTER_OVERLAP
1982         if (!ok)
1983             Tkinter_Error(self);
1984         else {
1985             res = Py_None;
1986             Py_INCREF(res);
1987         }
1988         LEAVE_OVERLAP_TCL
1989         break;
1990     default:
1991         PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1992         return NULL;
1993     }
1994     return res;
1995 }
1996 
1997 static PyObject *
Tkapp_SetVar(PyObject * self,PyObject * args)1998 Tkapp_SetVar(PyObject *self, PyObject *args)
1999 {
2000     return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
2001 }
2002 
2003 static PyObject *
Tkapp_GlobalSetVar(PyObject * self,PyObject * args)2004 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
2005 {
2006     return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
2007 }
2008 
2009 
2010 
2011 static PyObject *
GetVar(PyObject * self,PyObject * args,int flags)2012 GetVar(PyObject *self, PyObject *args, int flags)
2013 {
2014     char *name1, *name2=NULL;
2015     PyObject *res = NULL;
2016     Tcl_Obj *tres;
2017 
2018     if (!PyArg_ParseTuple(args, "O&|s:getvar",
2019                           varname_converter, &name1, &name2))
2020         return NULL;
2021 
2022     CHECK_STRING_LENGTH(name2);
2023     ENTER_TCL
2024     tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
2025     ENTER_OVERLAP
2026     if (tres == NULL) {
2027         PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2028     } else {
2029         if (((TkappObject*)self)->wantobjects) {
2030             res = FromObj(self, tres);
2031         }
2032         else {
2033             int len;
2034             char *s = Tcl_GetStringFromObj(tres, &len);
2035             res = PyString_FromStringAndSize(s, len);
2036         }
2037     }
2038     LEAVE_OVERLAP_TCL
2039     return res;
2040 }
2041 
2042 static PyObject *
Tkapp_GetVar(PyObject * self,PyObject * args)2043 Tkapp_GetVar(PyObject *self, PyObject *args)
2044 {
2045     return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
2046 }
2047 
2048 static PyObject *
Tkapp_GlobalGetVar(PyObject * self,PyObject * args)2049 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
2050 {
2051     return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
2052 }
2053 
2054 
2055 
2056 static PyObject *
UnsetVar(PyObject * self,PyObject * args,int flags)2057 UnsetVar(PyObject *self, PyObject *args, int flags)
2058 {
2059     char *name1, *name2=NULL;
2060     int code;
2061     PyObject *res = NULL;
2062 
2063     if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
2064         return NULL;
2065 
2066     CHECK_STRING_LENGTH(name1);
2067     CHECK_STRING_LENGTH(name2);
2068     ENTER_TCL
2069     code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
2070     ENTER_OVERLAP
2071     if (code == TCL_ERROR)
2072         res = Tkinter_Error(self);
2073     else {
2074         Py_INCREF(Py_None);
2075         res = Py_None;
2076     }
2077     LEAVE_OVERLAP_TCL
2078     return res;
2079 }
2080 
2081 static PyObject *
Tkapp_UnsetVar(PyObject * self,PyObject * args)2082 Tkapp_UnsetVar(PyObject *self, PyObject *args)
2083 {
2084     return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
2085 }
2086 
2087 static PyObject *
Tkapp_GlobalUnsetVar(PyObject * self,PyObject * args)2088 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
2089 {
2090     return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
2091 }
2092 
2093 
2094 
2095 /** Tcl to Python **/
2096 
2097 static PyObject *
Tkapp_GetInt(PyObject * self,PyObject * args)2098 Tkapp_GetInt(PyObject *self, PyObject *args)
2099 {
2100     char *s;
2101 #if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2102     Tcl_Obj *value;
2103     PyObject *result;
2104 #else
2105     int intValue;
2106 #endif
2107 
2108     if (PyTuple_Size(args) == 1) {
2109         PyObject* o = PyTuple_GetItem(args, 0);
2110         if (PyInt_Check(o) || PyLong_Check(o)) {
2111             Py_INCREF(o);
2112             return o;
2113         }
2114     }
2115     if (!PyArg_ParseTuple(args, "s:getint", &s))
2116         return NULL;
2117     CHECK_STRING_LENGTH(s);
2118 #if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2119     value = Tcl_NewStringObj(s, -1);
2120     if (value == NULL)
2121         return Tkinter_Error(self);
2122     /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2123        in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2124 
2125        Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2126        value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2127      */
2128 #ifdef HAVE_LIBTOMMAMTH
2129     result = fromBignumObj(self, value);
2130 #else
2131     result = fromWideIntObj(self, value);
2132 #endif
2133     Tcl_DecrRefCount(value);
2134     if (result != NULL)
2135         return PyNumber_Int(result);
2136     if (PyErr_Occurred())
2137         return NULL;
2138 #else
2139     if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
2140         return PyInt_FromLong(intValue);
2141 #endif
2142     return Tkinter_Error(self);
2143 }
2144 
2145 static PyObject *
Tkapp_GetDouble(PyObject * self,PyObject * args)2146 Tkapp_GetDouble(PyObject *self, PyObject *args)
2147 {
2148     char *s;
2149     double v;
2150 
2151     if (PyTuple_Size(args) == 1) {
2152         PyObject *o = PyTuple_GetItem(args, 0);
2153         if (PyFloat_Check(o)) {
2154             Py_INCREF(o);
2155             return o;
2156         }
2157     }
2158     if (!PyArg_ParseTuple(args, "s:getdouble", &s))
2159         return NULL;
2160     CHECK_STRING_LENGTH(s);
2161     if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2162         return Tkinter_Error(self);
2163     return Py_BuildValue("d", v);
2164 }
2165 
2166 static PyObject *
Tkapp_GetBoolean(PyObject * self,PyObject * arg)2167 Tkapp_GetBoolean(PyObject *self, PyObject *arg)
2168 {
2169     char *s;
2170     int v;
2171 
2172     if (PyInt_Check(arg)) /* int or bool */
2173         return PyBool_FromLong(PyInt_AS_LONG(arg));
2174 
2175     if (PyLong_Check(arg))
2176         return PyBool_FromLong(Py_SIZE(arg) != 0);
2177 
2178     if (PyTclObject_Check(arg)) {
2179         if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2180                                   ((PyTclObject*)arg)->value,
2181                                   &v) == TCL_ERROR)
2182             return Tkinter_Error(self);
2183         return PyBool_FromLong(v);
2184     }
2185 
2186     if (!PyArg_Parse(arg, "s:getboolean", &s))
2187         return NULL;
2188     CHECK_STRING_LENGTH(s);
2189     if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2190         return Tkinter_Error(self);
2191     return PyBool_FromLong(v);
2192 }
2193 
2194 static PyObject *
Tkapp_ExprString(PyObject * self,PyObject * args)2195 Tkapp_ExprString(PyObject *self, PyObject *args)
2196 {
2197     char *s;
2198     PyObject *res = NULL;
2199     int retval;
2200 
2201     if (!PyArg_ParseTuple(args, "s:exprstring", &s))
2202         return NULL;
2203 
2204     CHECK_STRING_LENGTH(s);
2205     CHECK_TCL_APPARTMENT;
2206 
2207     ENTER_TCL
2208     retval = Tcl_ExprString(Tkapp_Interp(self), s);
2209     ENTER_OVERLAP
2210     if (retval == TCL_ERROR)
2211         res = Tkinter_Error(self);
2212     else
2213         res = PyString_FromString(Tkapp_Result(self));
2214     LEAVE_OVERLAP_TCL
2215     return res;
2216 }
2217 
2218 static PyObject *
Tkapp_ExprLong(PyObject * self,PyObject * args)2219 Tkapp_ExprLong(PyObject *self, PyObject *args)
2220 {
2221     char *s;
2222     PyObject *res = NULL;
2223     int retval;
2224     long v;
2225 
2226     if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2227         return NULL;
2228 
2229     CHECK_STRING_LENGTH(s);
2230     CHECK_TCL_APPARTMENT;
2231 
2232     ENTER_TCL
2233     retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2234     ENTER_OVERLAP
2235     if (retval == TCL_ERROR)
2236         res = Tkinter_Error(self);
2237     else
2238         res = Py_BuildValue("l", v);
2239     LEAVE_OVERLAP_TCL
2240     return res;
2241 }
2242 
2243 static PyObject *
Tkapp_ExprDouble(PyObject * self,PyObject * args)2244 Tkapp_ExprDouble(PyObject *self, PyObject *args)
2245 {
2246     char *s;
2247     PyObject *res = NULL;
2248     double v;
2249     int retval;
2250 
2251     if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2252         return NULL;
2253     CHECK_STRING_LENGTH(s);
2254     CHECK_TCL_APPARTMENT;
2255     PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2256     ENTER_TCL
2257     retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2258     ENTER_OVERLAP
2259     PyFPE_END_PROTECT(retval)
2260     if (retval == TCL_ERROR)
2261         res = Tkinter_Error(self);
2262     else
2263         res = Py_BuildValue("d", v);
2264     LEAVE_OVERLAP_TCL
2265     return res;
2266 }
2267 
2268 static PyObject *
Tkapp_ExprBoolean(PyObject * self,PyObject * args)2269 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
2270 {
2271     char *s;
2272     PyObject *res = NULL;
2273     int retval;
2274     int v;
2275 
2276     if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2277         return NULL;
2278     CHECK_STRING_LENGTH(s);
2279     CHECK_TCL_APPARTMENT;
2280     ENTER_TCL
2281     retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2282     ENTER_OVERLAP
2283     if (retval == TCL_ERROR)
2284         res = Tkinter_Error(self);
2285     else
2286         res = Py_BuildValue("i", v);
2287     LEAVE_OVERLAP_TCL
2288     return res;
2289 }
2290 
2291 
2292 
2293 static PyObject *
Tkapp_SplitList(PyObject * self,PyObject * args)2294 Tkapp_SplitList(PyObject *self, PyObject *args)
2295 {
2296     char *list;
2297     int argc;
2298     char **argv;
2299     PyObject *arg, *v;
2300     int i;
2301 
2302     if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2303         return NULL;
2304     if (PyTclObject_Check(arg)) {
2305         int objc;
2306         Tcl_Obj **objv;
2307         if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2308                                    ((PyTclObject*)arg)->value,
2309                                    &objc, &objv) == TCL_ERROR) {
2310             return Tkinter_Error(self);
2311         }
2312         if (!(v = PyTuple_New(objc)))
2313             return NULL;
2314         for (i = 0; i < objc; i++) {
2315             PyObject *s = FromObj(self, objv[i]);
2316             if (!s || PyTuple_SetItem(v, i, s)) {
2317                 Py_DECREF(v);
2318                 return NULL;
2319             }
2320         }
2321         return v;
2322     }
2323     if (PyTuple_Check(arg)) {
2324         Py_INCREF(arg);
2325         return arg;
2326     }
2327 
2328     if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2329         return NULL;
2330 
2331     CHECK_STRING_LENGTH(list);
2332     if (Tcl_SplitList(Tkapp_Interp(self), list,
2333                       &argc, &argv) == TCL_ERROR)  {
2334         PyMem_Free(list);
2335         return Tkinter_Error(self);
2336     }
2337 
2338     if (!(v = PyTuple_New(argc)))
2339         goto finally;
2340 
2341     for (i = 0; i < argc; i++) {
2342         PyObject *s = PyString_FromString(argv[i]);
2343         if (!s || PyTuple_SetItem(v, i, s)) {
2344             Py_DECREF(v);
2345             v = NULL;
2346             goto finally;
2347         }
2348     }
2349 
2350   finally:
2351     ckfree(FREECAST argv);
2352     PyMem_Free(list);
2353     return v;
2354 }
2355 
2356 static PyObject *
Tkapp_Split(PyObject * self,PyObject * args)2357 Tkapp_Split(PyObject *self, PyObject *args)
2358 {
2359     PyObject *arg, *v;
2360     char *list;
2361 
2362     if (!PyArg_ParseTuple(args, "O:split", &arg))
2363         return NULL;
2364     if (PyTclObject_Check(arg)) {
2365         Tcl_Obj *value = ((PyTclObject*)arg)->value;
2366         int objc;
2367         Tcl_Obj **objv;
2368         int i;
2369         if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2370                                    &objc, &objv) == TCL_ERROR) {
2371             return FromObj(self, value);
2372         }
2373         if (objc == 0)
2374             return PyString_FromString("");
2375         if (objc == 1)
2376             return FromObj(self, objv[0]);
2377         if (!(v = PyTuple_New(objc)))
2378             return NULL;
2379         for (i = 0; i < objc; i++) {
2380             PyObject *s = FromObj(self, objv[i]);
2381             if (!s || PyTuple_SetItem(v, i, s)) {
2382                 Py_DECREF(v);
2383                 return NULL;
2384             }
2385         }
2386         return v;
2387     }
2388     if (PyTuple_Check(arg))
2389         return SplitObj(arg);
2390 
2391     if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2392         return NULL;
2393     CHECK_STRING_LENGTH(list);
2394     v = Split(list);
2395     PyMem_Free(list);
2396     return v;
2397 }
2398 
2399 static PyObject *
Tkapp_Merge(PyObject * self,PyObject * args)2400 Tkapp_Merge(PyObject *self, PyObject *args)
2401 {
2402     char *s = Merge(args);
2403     PyObject *res = NULL;
2404 
2405     if (s) {
2406         res = PyString_FromString(s);
2407         ckfree(s);
2408     }
2409 
2410     return res;
2411 }
2412 
2413 
2414 
2415 /** Tcl Command **/
2416 
2417 /* Client data struct */
2418 typedef struct {
2419     PyObject *self;
2420     PyObject *func;
2421 } PythonCmd_ClientData;
2422 
2423 static int
PythonCmd_Error(Tcl_Interp * interp)2424 PythonCmd_Error(Tcl_Interp *interp)
2425 {
2426     errorInCmd = 1;
2427     PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2428     LEAVE_PYTHON
2429     return TCL_ERROR;
2430 }
2431 
2432 /* This is the Tcl command that acts as a wrapper for Python
2433  * function or method.
2434  */
2435 static int
PythonCmd(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])2436 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2437 {
2438     PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2439     PyObject *func, *arg, *res;
2440     int i, rv;
2441     Tcl_Obj *obj_res;
2442 
2443     ENTER_PYTHON
2444 
2445     /* TBD: no error checking here since we know, via the
2446      * Tkapp_CreateCommand() that the client data is a two-tuple
2447      */
2448     func = data->func;
2449 
2450     /* Create argument list (argv1, ..., argvN) */
2451     if (!(arg = PyTuple_New(argc - 1)))
2452         return PythonCmd_Error(interp);
2453 
2454     for (i = 0; i < (argc - 1); i++) {
2455         PyObject *s = fromTclString(argv[i + 1]);
2456         if (!s || PyTuple_SetItem(arg, i, s)) {
2457             Py_DECREF(arg);
2458             return PythonCmd_Error(interp);
2459         }
2460     }
2461     res = PyEval_CallObject(func, arg);
2462     Py_DECREF(arg);
2463 
2464     if (res == NULL)
2465         return PythonCmd_Error(interp);
2466 
2467     obj_res = AsObj(res);
2468     if (obj_res == NULL) {
2469         Py_DECREF(res);
2470         return PythonCmd_Error(interp);
2471     }
2472     else {
2473         Tcl_SetObjResult(interp, obj_res);
2474         rv = TCL_OK;
2475     }
2476 
2477     Py_DECREF(res);
2478 
2479     LEAVE_PYTHON
2480 
2481     return rv;
2482 }
2483 
2484 static void
PythonCmdDelete(ClientData clientData)2485 PythonCmdDelete(ClientData clientData)
2486 {
2487     PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2488 
2489     ENTER_PYTHON
2490     Py_XDECREF(data->self);
2491     Py_XDECREF(data->func);
2492     PyMem_DEL(data);
2493     LEAVE_PYTHON
2494 }
2495 
2496 
2497 
2498 
2499 #ifdef WITH_THREAD
2500 TCL_DECLARE_MUTEX(command_mutex)
2501 
2502 typedef struct CommandEvent{
2503     Tcl_Event ev;
2504     Tcl_Interp* interp;
2505     char *name;
2506     int create;
2507     int *status;
2508     ClientData *data;
2509     Tcl_Condition *done;
2510 } CommandEvent;
2511 
2512 static int
Tkapp_CommandProc(CommandEvent * ev,int flags)2513 Tkapp_CommandProc(CommandEvent *ev, int flags)
2514 {
2515     if (ev->create)
2516         *ev->status = Tcl_CreateCommand(
2517             ev->interp, ev->name, PythonCmd,
2518             ev->data, PythonCmdDelete) == NULL;
2519     else
2520         *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2521     Tcl_MutexLock(&command_mutex);
2522     Tcl_ConditionNotify(ev->done);
2523     Tcl_MutexUnlock(&command_mutex);
2524     return 1;
2525 }
2526 #endif
2527 
2528 static PyObject *
Tkapp_CreateCommand(PyObject * selfptr,PyObject * args)2529 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2530 {
2531     TkappObject *self = (TkappObject*)selfptr;
2532     PythonCmd_ClientData *data;
2533     char *cmdName;
2534     PyObject *func;
2535     int err;
2536 
2537     if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2538         return NULL;
2539     CHECK_STRING_LENGTH(cmdName);
2540     if (!PyCallable_Check(func)) {
2541         PyErr_SetString(PyExc_TypeError, "command not callable");
2542         return NULL;
2543     }
2544 
2545 #ifdef WITH_THREAD
2546     if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2547         !WaitForMainloop(self))
2548         return NULL;
2549 #endif
2550 
2551     data = PyMem_NEW(PythonCmd_ClientData, 1);
2552     if (!data)
2553         return PyErr_NoMemory();
2554     Py_INCREF(self);
2555     Py_INCREF(func);
2556     data->self = selfptr;
2557     data->func = func;
2558 
2559 #ifdef WITH_THREAD
2560     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2561         Tcl_Condition cond = NULL;
2562         CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2563         if (ev == NULL) {
2564             PyErr_NoMemory();
2565             PyMem_DEL(data);
2566             return NULL;
2567         }
2568         ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2569         ev->interp = self->interp;
2570         ev->create = 1;
2571         ev->name = cmdName;
2572         ev->data = (ClientData)data;
2573         ev->status = &err;
2574         ev->done = &cond;
2575         Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2576         Tcl_ConditionFinalize(&cond);
2577     }
2578     else
2579 #endif
2580     {
2581         ENTER_TCL
2582         err = Tcl_CreateCommand(
2583             Tkapp_Interp(self), cmdName, PythonCmd,
2584             (ClientData)data, PythonCmdDelete) == NULL;
2585         LEAVE_TCL
2586     }
2587     if (err) {
2588         PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2589         PyMem_DEL(data);
2590         return NULL;
2591     }
2592 
2593     Py_INCREF(Py_None);
2594     return Py_None;
2595 }
2596 
2597 
2598 
2599 static PyObject *
Tkapp_DeleteCommand(PyObject * selfptr,PyObject * args)2600 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2601 {
2602     TkappObject *self = (TkappObject*)selfptr;
2603     char *cmdName;
2604     int err;
2605 
2606     if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2607         return NULL;
2608     CHECK_STRING_LENGTH(cmdName);
2609 
2610 #ifdef WITH_THREAD
2611     if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2612         Tcl_Condition cond = NULL;
2613         CommandEvent *ev;
2614         ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2615         if (ev == NULL) {
2616             PyErr_NoMemory();
2617             return NULL;
2618         }
2619         ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2620         ev->interp = self->interp;
2621         ev->create = 0;
2622         ev->name = cmdName;
2623         ev->status = &err;
2624         ev->done = &cond;
2625         Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2626                          &command_mutex);
2627         Tcl_ConditionFinalize(&cond);
2628     }
2629     else
2630 #endif
2631     {
2632         ENTER_TCL
2633         err = Tcl_DeleteCommand(self->interp, cmdName);
2634         LEAVE_TCL
2635     }
2636     if (err == -1) {
2637         PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2638         return NULL;
2639     }
2640     Py_INCREF(Py_None);
2641     return Py_None;
2642 }
2643 
2644 
2645 
2646 #ifdef HAVE_CREATEFILEHANDLER
2647 /** File Handler **/
2648 
2649 typedef struct _fhcdata {
2650     PyObject *func;
2651     PyObject *file;
2652     int id;
2653     struct _fhcdata *next;
2654 } FileHandler_ClientData;
2655 
2656 static FileHandler_ClientData *HeadFHCD;
2657 
2658 static FileHandler_ClientData *
NewFHCD(PyObject * func,PyObject * file,int id)2659 NewFHCD(PyObject *func, PyObject *file, int id)
2660 {
2661     FileHandler_ClientData *p;
2662     p = PyMem_NEW(FileHandler_ClientData, 1);
2663     if (p != NULL) {
2664         Py_XINCREF(func);
2665         Py_XINCREF(file);
2666         p->func = func;
2667         p->file = file;
2668         p->id = id;
2669         p->next = HeadFHCD;
2670         HeadFHCD = p;
2671     }
2672     return p;
2673 }
2674 
2675 static void
DeleteFHCD(int id)2676 DeleteFHCD(int id)
2677 {
2678     FileHandler_ClientData *p, **pp;
2679 
2680     pp = &HeadFHCD;
2681     while ((p = *pp) != NULL) {
2682         if (p->id == id) {
2683             *pp = p->next;
2684             Py_XDECREF(p->func);
2685             Py_XDECREF(p->file);
2686             PyMem_DEL(p);
2687         }
2688         else
2689             pp = &p->next;
2690     }
2691 }
2692 
2693 static void
FileHandler(ClientData clientData,int mask)2694 FileHandler(ClientData clientData, int mask)
2695 {
2696     FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2697     PyObject *func, *file, *arg, *res;
2698 
2699     ENTER_PYTHON
2700     func = data->func;
2701     file = data->file;
2702 
2703     arg = Py_BuildValue("(Oi)", file, (long) mask);
2704     res = PyEval_CallObject(func, arg);
2705     Py_DECREF(arg);
2706 
2707     if (res == NULL) {
2708         errorInCmd = 1;
2709         PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2710     }
2711     Py_XDECREF(res);
2712     LEAVE_PYTHON
2713 }
2714 
2715 static PyObject *
Tkapp_CreateFileHandler(PyObject * self,PyObject * args)2716 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2717      /* args is (file, mask, func) */
2718 {
2719     FileHandler_ClientData *data;
2720     PyObject *file, *func;
2721     int mask, tfile;
2722 
2723     if (!self && Py_Py3kWarningFlag) {
2724         if (PyErr_Warn(PyExc_DeprecationWarning,
2725                                 "_tkinter.createfilehandler is gone in 3.x") < 0)
2726             return NULL;
2727     }
2728 
2729     if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2730                           &file, &mask, &func))
2731         return NULL;
2732 
2733 #ifdef WITH_THREAD
2734     if (!self && !tcl_lock) {
2735         /* We don't have the Tcl lock since Tcl is threaded. */
2736         PyErr_SetString(PyExc_RuntimeError,
2737                         "_tkinter.createfilehandler not supported "
2738                         "for threaded Tcl");
2739         return NULL;
2740     }
2741 #endif
2742 
2743     if (self) {
2744         CHECK_TCL_APPARTMENT;
2745     }
2746 
2747     tfile = PyObject_AsFileDescriptor(file);
2748     if (tfile < 0)
2749         return NULL;
2750     if (!PyCallable_Check(func)) {
2751         PyErr_SetString(PyExc_TypeError, "bad argument list");
2752         return NULL;
2753     }
2754 
2755     data = NewFHCD(func, file, tfile);
2756     if (data == NULL)
2757         return NULL;
2758 
2759     /* Ought to check for null Tcl_File object... */
2760     ENTER_TCL
2761     Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2762     LEAVE_TCL
2763     Py_INCREF(Py_None);
2764     return Py_None;
2765 }
2766 
2767 static PyObject *
Tkapp_DeleteFileHandler(PyObject * self,PyObject * args)2768 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2769 {
2770     PyObject *file;
2771     int tfile;
2772 
2773     if (!self && Py_Py3kWarningFlag) {
2774         if (PyErr_Warn(PyExc_DeprecationWarning,
2775                                 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2776             return NULL;
2777     }
2778 
2779     if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2780         return NULL;
2781 
2782 #ifdef WITH_THREAD
2783     if (!self && !tcl_lock) {
2784         /* We don't have the Tcl lock since Tcl is threaded. */
2785         PyErr_SetString(PyExc_RuntimeError,
2786                         "_tkinter.deletefilehandler not supported "
2787                         "for threaded Tcl");
2788         return NULL;
2789     }
2790 #endif
2791 
2792     if (self) {
2793         CHECK_TCL_APPARTMENT;
2794     }
2795 
2796     tfile = PyObject_AsFileDescriptor(file);
2797     if (tfile < 0)
2798         return NULL;
2799 
2800     DeleteFHCD(tfile);
2801 
2802     /* Ought to check for null Tcl_File object... */
2803     ENTER_TCL
2804     Tcl_DeleteFileHandler(tfile);
2805     LEAVE_TCL
2806     Py_INCREF(Py_None);
2807     return Py_None;
2808 }
2809 #endif /* HAVE_CREATEFILEHANDLER */
2810 
2811 
2812 /**** Tktt Object (timer token) ****/
2813 
2814 static PyTypeObject Tktt_Type;
2815 
2816 typedef struct {
2817     PyObject_HEAD
2818     Tcl_TimerToken token;
2819     PyObject *func;
2820 } TkttObject;
2821 
2822 static PyObject *
Tktt_DeleteTimerHandler(PyObject * self,PyObject * args)2823 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2824 {
2825     TkttObject *v = (TkttObject *)self;
2826     PyObject *func = v->func;
2827 
2828     if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2829         return NULL;
2830     if (v->token != NULL) {
2831         Tcl_DeleteTimerHandler(v->token);
2832         v->token = NULL;
2833     }
2834     if (func != NULL) {
2835         v->func = NULL;
2836         Py_DECREF(func);
2837         Py_DECREF(v); /* See Tktt_New() */
2838     }
2839     Py_INCREF(Py_None);
2840     return Py_None;
2841 }
2842 
2843 static PyMethodDef Tktt_methods[] =
2844 {
2845     {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2846     {NULL, NULL}
2847 };
2848 
2849 static TkttObject *
Tktt_New(PyObject * func)2850 Tktt_New(PyObject *func)
2851 {
2852     TkttObject *v;
2853 
2854     v = PyObject_New(TkttObject, &Tktt_Type);
2855     if (v == NULL)
2856         return NULL;
2857 
2858     Py_INCREF(func);
2859     v->token = NULL;
2860     v->func = func;
2861 
2862     /* Extra reference, deleted when called or when handler is deleted */
2863     Py_INCREF(v);
2864     return v;
2865 }
2866 
2867 static void
Tktt_Dealloc(PyObject * self)2868 Tktt_Dealloc(PyObject *self)
2869 {
2870     TkttObject *v = (TkttObject *)self;
2871     PyObject *func = v->func;
2872 
2873     Py_XDECREF(func);
2874 
2875     PyObject_Del(self);
2876 }
2877 
2878 static PyObject *
Tktt_Repr(PyObject * self)2879 Tktt_Repr(PyObject *self)
2880 {
2881     TkttObject *v = (TkttObject *)self;
2882     char buf[100];
2883 
2884     PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2885                     v->func == NULL ? ", handler deleted" : "");
2886     return PyString_FromString(buf);
2887 }
2888 
2889 static PyObject *
Tktt_GetAttr(PyObject * self,char * name)2890 Tktt_GetAttr(PyObject *self, char *name)
2891 {
2892     return Py_FindMethod(Tktt_methods, self, name);
2893 }
2894 
2895 static PyTypeObject Tktt_Type =
2896 {
2897     PyVarObject_HEAD_INIT(NULL, 0)
2898     "tktimertoken",                          /*tp_name */
2899     sizeof(TkttObject),                      /*tp_basicsize */
2900     0,                                       /*tp_itemsize */
2901     Tktt_Dealloc,                            /*tp_dealloc */
2902     0,                                       /*tp_print */
2903     Tktt_GetAttr,                            /*tp_getattr */
2904     0,                                       /*tp_setattr */
2905     0,                                       /*tp_compare */
2906     Tktt_Repr,                               /*tp_repr */
2907     0,                                       /*tp_as_number */
2908     0,                                       /*tp_as_sequence */
2909     0,                                       /*tp_as_mapping */
2910     0,                                       /*tp_hash */
2911 };
2912 
2913 
2914 
2915 /** Timer Handler **/
2916 
2917 static void
TimerHandler(ClientData clientData)2918 TimerHandler(ClientData clientData)
2919 {
2920     TkttObject *v = (TkttObject *)clientData;
2921     PyObject *func = v->func;
2922     PyObject *res;
2923 
2924     if (func == NULL)
2925         return;
2926 
2927     v->func = NULL;
2928 
2929     ENTER_PYTHON
2930 
2931     res  = PyEval_CallObject(func, NULL);
2932     Py_DECREF(func);
2933     Py_DECREF(v); /* See Tktt_New() */
2934 
2935     if (res == NULL) {
2936         errorInCmd = 1;
2937         PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2938     }
2939     else
2940         Py_DECREF(res);
2941 
2942     LEAVE_PYTHON
2943 }
2944 
2945 static PyObject *
Tkapp_CreateTimerHandler(PyObject * self,PyObject * args)2946 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2947 {
2948     int milliseconds;
2949     PyObject *func;
2950     TkttObject *v;
2951 
2952     if (!self && Py_Py3kWarningFlag) {
2953         if (PyErr_Warn(PyExc_DeprecationWarning,
2954                                 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2955             return NULL;
2956     }
2957 
2958     if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2959                           &milliseconds, &func))
2960         return NULL;
2961     if (!PyCallable_Check(func)) {
2962         PyErr_SetString(PyExc_TypeError, "bad argument list");
2963         return NULL;
2964     }
2965 
2966 #ifdef WITH_THREAD
2967     if (!self && !tcl_lock) {
2968         /* We don't have the Tcl lock since Tcl is threaded. */
2969         PyErr_SetString(PyExc_RuntimeError,
2970                         "_tkinter.createtimerhandler not supported "
2971                         "for threaded Tcl");
2972         return NULL;
2973     }
2974 #endif
2975 
2976     if (self) {
2977         CHECK_TCL_APPARTMENT;
2978     }
2979 
2980     v = Tktt_New(func);
2981     if (v) {
2982         v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2983                                           (ClientData)v);
2984     }
2985 
2986     return (PyObject *) v;
2987 }
2988 
2989 
2990 /** Event Loop **/
2991 
2992 static PyObject *
Tkapp_MainLoop(PyObject * selfptr,PyObject * args)2993 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2994 {
2995     int threshold = 0;
2996     TkappObject *self = (TkappObject*)selfptr;
2997 #ifdef WITH_THREAD
2998     PyThreadState *tstate = PyThreadState_Get();
2999 #endif
3000 
3001     if (!self && Py_Py3kWarningFlag) {
3002         if (PyErr_Warn(PyExc_DeprecationWarning,
3003                                 "_tkinter.mainloop is gone in 3.x") < 0)
3004             return NULL;
3005     }
3006 
3007     if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
3008         return NULL;
3009 
3010 #ifdef WITH_THREAD
3011     if (!self && !tcl_lock) {
3012         /* We don't have the Tcl lock since Tcl is threaded. */
3013         PyErr_SetString(PyExc_RuntimeError,
3014                         "_tkinter.mainloop not supported "
3015                         "for threaded Tcl");
3016         return NULL;
3017     }
3018 #endif
3019 
3020     if (self) {
3021         CHECK_TCL_APPARTMENT;
3022         self->dispatching = 1;
3023     }
3024 
3025     quitMainLoop = 0;
3026     while (Tk_GetNumMainWindows() > threshold &&
3027            !quitMainLoop &&
3028            !errorInCmd)
3029     {
3030         int result;
3031 
3032 #ifdef WITH_THREAD
3033         if (self && self->threaded) {
3034             /* Allow other Python threads to run. */
3035             ENTER_TCL
3036             result = Tcl_DoOneEvent(0);
3037             LEAVE_TCL
3038         }
3039         else {
3040             Py_BEGIN_ALLOW_THREADS
3041             if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3042             tcl_tstate = tstate;
3043             result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3044             tcl_tstate = NULL;
3045             if(tcl_lock)PyThread_release_lock(tcl_lock);
3046             if (result == 0)
3047                 Sleep(Tkinter_busywaitinterval);
3048             Py_END_ALLOW_THREADS
3049         }
3050 #else
3051         result = Tcl_DoOneEvent(0);
3052 #endif
3053 
3054         if (PyErr_CheckSignals() != 0) {
3055             if (self)
3056                 self->dispatching = 0;
3057             return NULL;
3058         }
3059         if (result < 0)
3060             break;
3061     }
3062     if (self)
3063         self->dispatching = 0;
3064     quitMainLoop = 0;
3065 
3066     if (errorInCmd) {
3067         errorInCmd = 0;
3068         PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3069         excInCmd = valInCmd = trbInCmd = NULL;
3070         return NULL;
3071     }
3072     Py_INCREF(Py_None);
3073     return Py_None;
3074 }
3075 
3076 static PyObject *
Tkapp_DoOneEvent(PyObject * self,PyObject * args)3077 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
3078 {
3079     int flags = 0;
3080     int rv;
3081 
3082     if (!self && Py_Py3kWarningFlag) {
3083         if (PyErr_Warn(PyExc_DeprecationWarning,
3084                                 "_tkinter.dooneevent is gone in 3.x") < 0)
3085             return NULL;
3086     }
3087 
3088     if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
3089         return NULL;
3090 
3091     ENTER_TCL
3092     rv = Tcl_DoOneEvent(flags);
3093     LEAVE_TCL
3094     return Py_BuildValue("i", rv);
3095 }
3096 
3097 static PyObject *
Tkapp_Quit(PyObject * self,PyObject * args)3098 Tkapp_Quit(PyObject *self, PyObject *args)
3099 {
3100 
3101     if (!self && Py_Py3kWarningFlag) {
3102         if (PyErr_Warn(PyExc_DeprecationWarning,
3103                                 "_tkinter.quit is gone in 3.x") < 0)
3104             return NULL;
3105     }
3106 
3107     if (!PyArg_ParseTuple(args, ":quit"))
3108         return NULL;
3109 
3110     quitMainLoop = 1;
3111     Py_INCREF(Py_None);
3112     return Py_None;
3113 }
3114 
3115 static PyObject *
Tkapp_InterpAddr(PyObject * self,PyObject * args)3116 Tkapp_InterpAddr(PyObject *self, PyObject *args)
3117 {
3118 
3119     if (!PyArg_ParseTuple(args, ":interpaddr"))
3120         return NULL;
3121 
3122     return PyLong_FromVoidPtr(Tkapp_Interp(self));
3123 }
3124 
3125 static PyObject *
Tkapp_TkInit(PyObject * self,PyObject * args)3126 Tkapp_TkInit(PyObject *self, PyObject *args)
3127 {
3128     Tcl_Interp *interp = Tkapp_Interp(self);
3129     const char * _tk_exists = NULL;
3130     int err;
3131 
3132 #ifdef TKINTER_PROTECT_LOADTK
3133     /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3134      * first call failed.
3135      * To avoid the deadlock, we just refuse the second call through
3136      * a static variable.
3137      */
3138     if (tk_load_failed) {
3139         PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3140         return NULL;
3141     }
3142 #endif
3143 
3144     /* We want to guard against calling Tk_Init() multiple times */
3145     CHECK_TCL_APPARTMENT;
3146     ENTER_TCL
3147     err = Tcl_Eval(Tkapp_Interp(self), "info exists     tk_version");
3148     ENTER_OVERLAP
3149     if (err == TCL_ERROR) {
3150         /* This sets an exception, but we cannot return right
3151            away because we need to exit the overlap first. */
3152         Tkinter_Error(self);
3153     } else {
3154         _tk_exists = Tkapp_Result(self);
3155     }
3156     LEAVE_OVERLAP_TCL
3157     if (err == TCL_ERROR) {
3158         return NULL;
3159     }
3160     if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0)     {
3161         if (Tk_Init(interp)             == TCL_ERROR) {
3162             PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
3163 #ifdef TKINTER_PROTECT_LOADTK
3164             tk_load_failed = 1;
3165 #endif
3166             return NULL;
3167         }
3168     }
3169     Py_INCREF(Py_None);
3170     return Py_None;
3171 }
3172 
3173 static PyObject *
Tkapp_WantObjects(PyObject * self,PyObject * args)3174 Tkapp_WantObjects(PyObject *self, PyObject *args)
3175 {
3176 
3177     int wantobjects = -1;
3178     if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3179         return NULL;
3180     if (wantobjects == -1)
3181         return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3182     ((TkappObject*)self)->wantobjects = wantobjects;
3183 
3184     Py_INCREF(Py_None);
3185     return Py_None;
3186 }
3187 
3188 static PyObject *
Tkapp_WillDispatch(PyObject * self,PyObject * args)3189 Tkapp_WillDispatch(PyObject *self, PyObject *args)
3190 {
3191 
3192     ((TkappObject*)self)->dispatching = 1;
3193 
3194     Py_INCREF(Py_None);
3195     return Py_None;
3196 }
3197 
3198 /* Convert Python string or any buffer compatible object to Tcl byte-array
3199  * object.  Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
3200  */
3201 static PyObject *
Tkapp_CreateByteArray(PyObject * self,PyObject * args)3202 Tkapp_CreateByteArray(PyObject *self, PyObject *args)
3203 {
3204     Py_buffer view;
3205     Tcl_Obj* obj;
3206     PyObject *res = NULL;
3207 
3208     if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
3209         return NULL;
3210 
3211     if (view.len >= INT_MAX) {
3212         PyErr_SetString(PyExc_OverflowError, "string is too long");
3213         return NULL;
3214     }
3215     obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
3216     if (obj == NULL) {
3217         PyBuffer_Release(&view);
3218         return Tkinter_Error(self);
3219     }
3220     res = newPyTclObject(obj);
3221     PyBuffer_Release(&view);
3222     return res;
3223 }
3224 
3225 
3226 /**** Tkapp Method List ****/
3227 
3228 static PyMethodDef Tkapp_methods[] =
3229 {
3230     {"willdispatch",       Tkapp_WillDispatch, METH_NOARGS},
3231     {"wantobjects",            Tkapp_WantObjects, METH_VARARGS},
3232     {"call",                   Tkapp_Call, METH_VARARGS},
3233     {"globalcall",             Tkapp_GlobalCall, METH_VARARGS},
3234     {"eval",                   Tkapp_Eval, METH_VARARGS},
3235     {"globaleval",             Tkapp_GlobalEval, METH_VARARGS},
3236     {"evalfile",               Tkapp_EvalFile, METH_VARARGS},
3237     {"record",                 Tkapp_Record, METH_VARARGS},
3238     {"adderrorinfo",       Tkapp_AddErrorInfo, METH_VARARGS},
3239     {"setvar",                 Tkapp_SetVar, METH_VARARGS},
3240     {"globalsetvar",       Tkapp_GlobalSetVar, METH_VARARGS},
3241     {"getvar",                 Tkapp_GetVar, METH_VARARGS},
3242     {"globalgetvar",       Tkapp_GlobalGetVar, METH_VARARGS},
3243     {"unsetvar",               Tkapp_UnsetVar, METH_VARARGS},
3244     {"globalunsetvar",     Tkapp_GlobalUnsetVar, METH_VARARGS},
3245     {"getint",                 Tkapp_GetInt, METH_VARARGS},
3246     {"getdouble",              Tkapp_GetDouble, METH_VARARGS},
3247     {"getboolean",             Tkapp_GetBoolean, METH_O},
3248     {"exprstring",             Tkapp_ExprString, METH_VARARGS},
3249     {"exprlong",               Tkapp_ExprLong, METH_VARARGS},
3250     {"exprdouble",             Tkapp_ExprDouble, METH_VARARGS},
3251     {"exprboolean",        Tkapp_ExprBoolean, METH_VARARGS},
3252     {"splitlist",              Tkapp_SplitList, METH_VARARGS},
3253     {"split",                  Tkapp_Split, METH_VARARGS},
3254     {"merge",                  Tkapp_Merge, METH_VARARGS},
3255     {"createcommand",      Tkapp_CreateCommand, METH_VARARGS},
3256     {"deletecommand",      Tkapp_DeleteCommand, METH_VARARGS},
3257 #ifdef HAVE_CREATEFILEHANDLER
3258     {"createfilehandler",  Tkapp_CreateFileHandler, METH_VARARGS},
3259     {"deletefilehandler",  Tkapp_DeleteFileHandler, METH_VARARGS},
3260 #endif
3261     {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3262     {"mainloop",               Tkapp_MainLoop, METH_VARARGS},
3263     {"dooneevent",             Tkapp_DoOneEvent, METH_VARARGS},
3264     {"quit",                   Tkapp_Quit, METH_VARARGS},
3265     {"interpaddr",         Tkapp_InterpAddr, METH_VARARGS},
3266     {"loadtk",                 Tkapp_TkInit, METH_NOARGS},
3267     {"_createbytearray",       Tkapp_CreateByteArray, METH_VARARGS},
3268     {NULL,                     NULL}
3269 };
3270 
3271 
3272 
3273 /**** Tkapp Type Methods ****/
3274 
3275 static void
Tkapp_Dealloc(PyObject * self)3276 Tkapp_Dealloc(PyObject *self)
3277 {
3278     /*CHECK_TCL_APPARTMENT;*/
3279     ENTER_TCL
3280     Tcl_DeleteInterp(Tkapp_Interp(self));
3281     LEAVE_TCL
3282     PyObject_Del(self);
3283     DisableEventHook();
3284 }
3285 
3286 static PyObject *
Tkapp_GetAttr(PyObject * self,char * name)3287 Tkapp_GetAttr(PyObject *self, char *name)
3288 {
3289     return Py_FindMethod(Tkapp_methods, self, name);
3290 }
3291 
3292 static PyTypeObject Tkapp_Type =
3293 {
3294     PyVarObject_HEAD_INIT(NULL, 0)
3295     "tkapp",                                 /*tp_name */
3296     sizeof(TkappObject),                     /*tp_basicsize */
3297     0,                                       /*tp_itemsize */
3298     Tkapp_Dealloc,                           /*tp_dealloc */
3299     0,                                       /*tp_print */
3300     Tkapp_GetAttr,                           /*tp_getattr */
3301     0,                                       /*tp_setattr */
3302     0,                                       /*tp_compare */
3303     0,                                       /*tp_repr */
3304     0,                                       /*tp_as_number */
3305     0,                                       /*tp_as_sequence */
3306     0,                                       /*tp_as_mapping */
3307     0,                                       /*tp_hash */
3308 };
3309 
3310 
3311 
3312 /**** Tkinter Module ****/
3313 
3314 typedef struct {
3315     PyObject* tuple;
3316     int size; /* current size */
3317     int maxsize; /* allocated size */
3318 } FlattenContext;
3319 
3320 static int
_bump(FlattenContext * context,int size)3321 _bump(FlattenContext* context, int size)
3322 {
3323     /* expand tuple to hold (at least) size new items.
3324        return true if successful, false if an exception was raised */
3325 
3326     int maxsize = context->maxsize * 2;
3327 
3328     if (maxsize < context->size + size)
3329         maxsize = context->size + size;
3330 
3331     context->maxsize = maxsize;
3332 
3333     return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
3334 }
3335 
3336 static int
_flatten1(FlattenContext * context,PyObject * item,int depth)3337 _flatten1(FlattenContext* context, PyObject* item, int depth)
3338 {
3339     /* add tuple or list to argument tuple (recursively) */
3340 
3341     int i, size;
3342 
3343     if (depth > 1000) {
3344         PyErr_SetString(PyExc_ValueError,
3345                         "nesting too deep in _flatten");
3346         return 0;
3347     } else if (PyList_Check(item)) {
3348         size = PyList_GET_SIZE(item);
3349         /* preallocate (assume no nesting) */
3350         if (context->size + size > context->maxsize &&
3351             !_bump(context, size))
3352             return 0;
3353         /* copy items to output tuple */
3354         for (i = 0; i < size; i++) {
3355             PyObject *o = PyList_GET_ITEM(item, i);
3356             if (PyList_Check(o) || PyTuple_Check(o)) {
3357                 if (!_flatten1(context, o, depth + 1))
3358                     return 0;
3359             } else if (o != Py_None) {
3360                 if (context->size + 1 > context->maxsize &&
3361                     !_bump(context, 1))
3362                     return 0;
3363                 Py_INCREF(o);
3364                 PyTuple_SET_ITEM(context->tuple,
3365                                  context->size++, o);
3366             }
3367         }
3368     } else if (PyTuple_Check(item)) {
3369         /* same, for tuples */
3370         size = PyTuple_GET_SIZE(item);
3371         if (context->size + size > context->maxsize &&
3372             !_bump(context, size))
3373             return 0;
3374         for (i = 0; i < size; i++) {
3375             PyObject *o = PyTuple_GET_ITEM(item, i);
3376             if (PyList_Check(o) || PyTuple_Check(o)) {
3377                 if (!_flatten1(context, o, depth + 1))
3378                     return 0;
3379             } else if (o != Py_None) {
3380                 if (context->size + 1 > context->maxsize &&
3381                     !_bump(context, 1))
3382                     return 0;
3383                 Py_INCREF(o);
3384                 PyTuple_SET_ITEM(context->tuple,
3385                                  context->size++, o);
3386             }
3387         }
3388     } else {
3389         PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3390         return 0;
3391     }
3392     return 1;
3393 }
3394 
3395 static PyObject *
Tkinter_Flatten(PyObject * self,PyObject * args)3396 Tkinter_Flatten(PyObject* self, PyObject* args)
3397 {
3398     FlattenContext context;
3399     PyObject* item;
3400 
3401     if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3402         return NULL;
3403 
3404     context.maxsize = PySequence_Size(item);
3405     if (context.maxsize < 0)
3406         return NULL;
3407     if (context.maxsize == 0)
3408         return PyTuple_New(0);
3409 
3410     context.tuple = PyTuple_New(context.maxsize);
3411     if (!context.tuple)
3412         return NULL;
3413 
3414     context.size = 0;
3415 
3416     if (!_flatten1(&context, item,0))
3417         return NULL;
3418 
3419     if (_PyTuple_Resize(&context.tuple, context.size))
3420         return NULL;
3421 
3422     return context.tuple;
3423 }
3424 
3425 static PyObject *
Tkinter_Create(PyObject * self,PyObject * args)3426 Tkinter_Create(PyObject *self, PyObject *args)
3427 {
3428     char *screenName = NULL;
3429     char *baseName = NULL;
3430     char *className = NULL;
3431     int interactive = 0;
3432     int wantobjects = 0;
3433     int wantTk = 1;     /* If false, then Tk_Init() doesn't get called */
3434     int sync = 0; /* pass -sync to wish */
3435     char *use = NULL; /* pass -use to wish */
3436 
3437     baseName = strrchr(Py_GetProgramName(), '/');
3438     if (baseName != NULL)
3439         baseName++;
3440     else
3441         baseName = Py_GetProgramName();
3442     className = "Tk";
3443 
3444     if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3445                           &screenName, &baseName, &className,
3446                           &interactive, &wantobjects, &wantTk,
3447                           &sync, &use))
3448         return NULL;
3449     CHECK_STRING_LENGTH(screenName);
3450     CHECK_STRING_LENGTH(baseName);
3451     CHECK_STRING_LENGTH(className);
3452     CHECK_STRING_LENGTH(use);
3453 
3454     return (PyObject *) Tkapp_New(screenName, baseName, className,
3455                                   interactive, wantobjects,     wantTk,
3456                                   sync, use);
3457 }
3458 
3459 static PyObject *
Tkinter_setbusywaitinterval(PyObject * self,PyObject * args)3460 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3461 {
3462     int new_val;
3463     if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3464         return NULL;
3465     if (new_val < 0) {
3466         PyErr_SetString(PyExc_ValueError,
3467                         "busywaitinterval must be >= 0");
3468         return NULL;
3469     }
3470     Tkinter_busywaitinterval = new_val;
3471     Py_INCREF(Py_None);
3472     return Py_None;
3473 }
3474 
3475 static char setbusywaitinterval_doc[] =
3476 "setbusywaitinterval(n) -> None\n\
3477 \n\
3478 Set the busy-wait interval in milliseconds between successive\n\
3479 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3480 It should be set to a divisor of the maximum time between\n\
3481 frames in an animation.";
3482 
3483 static PyObject *
Tkinter_getbusywaitinterval(PyObject * self,PyObject * args)3484 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3485 {
3486     return PyInt_FromLong(Tkinter_busywaitinterval);
3487 }
3488 
3489 static char getbusywaitinterval_doc[] =
3490 "getbusywaitinterval() -> int\n\
3491 \n\
3492 Return the current busy-wait interval between successive\n\
3493 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3494 
3495 static PyMethodDef moduleMethods[] =
3496 {
3497     {"_flatten",           Tkinter_Flatten, METH_VARARGS},
3498     {"create",             Tkinter_Create, METH_VARARGS},
3499 #ifdef HAVE_CREATEFILEHANDLER
3500     {"createfilehandler",  Tkapp_CreateFileHandler, METH_VARARGS},
3501     {"deletefilehandler",  Tkapp_DeleteFileHandler, METH_VARARGS},
3502 #endif
3503     {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3504     {"mainloop",           Tkapp_MainLoop, METH_VARARGS},
3505     {"dooneevent",         Tkapp_DoOneEvent, METH_VARARGS},
3506     {"quit",               Tkapp_Quit, METH_VARARGS},
3507     {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3508                            setbusywaitinterval_doc},
3509     {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3510                            METH_NOARGS, getbusywaitinterval_doc},
3511     {NULL,                 NULL}
3512 };
3513 
3514 #ifdef WAIT_FOR_STDIN
3515 
3516 static int stdin_ready = 0;
3517 
3518 #ifndef MS_WINDOWS
3519 static void
MyFileProc(void * clientData,int mask)3520 MyFileProc(void *clientData, int mask)
3521 {
3522     stdin_ready = 1;
3523 }
3524 #endif
3525 
3526 #ifdef WITH_THREAD
3527 static PyThreadState *event_tstate = NULL;
3528 #endif
3529 
3530 static int
EventHook(void)3531 EventHook(void)
3532 {
3533 #ifndef MS_WINDOWS
3534     int tfile;
3535 #endif
3536 #ifdef WITH_THREAD
3537     PyEval_RestoreThread(event_tstate);
3538 #endif
3539     stdin_ready = 0;
3540     errorInCmd = 0;
3541 #ifndef MS_WINDOWS
3542     tfile = fileno(stdin);
3543     Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3544 #endif
3545     while (!errorInCmd && !stdin_ready) {
3546         int result;
3547 #ifdef MS_WINDOWS
3548         if (_kbhit()) {
3549             stdin_ready = 1;
3550             break;
3551         }
3552 #endif
3553 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3554         Py_BEGIN_ALLOW_THREADS
3555         if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3556         tcl_tstate = event_tstate;
3557 
3558         result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3559 
3560         tcl_tstate = NULL;
3561         if(tcl_lock)PyThread_release_lock(tcl_lock);
3562         if (result == 0)
3563             Sleep(Tkinter_busywaitinterval);
3564         Py_END_ALLOW_THREADS
3565 #else
3566         result = Tcl_DoOneEvent(0);
3567 #endif
3568 
3569         if (result < 0)
3570             break;
3571     }
3572 #ifndef MS_WINDOWS
3573     Tcl_DeleteFileHandler(tfile);
3574 #endif
3575     if (errorInCmd) {
3576         errorInCmd = 0;
3577         PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3578         excInCmd = valInCmd = trbInCmd = NULL;
3579         PyErr_Print();
3580     }
3581 #ifdef WITH_THREAD
3582     PyEval_SaveThread();
3583 #endif
3584     return 0;
3585 }
3586 
3587 #endif
3588 
3589 static void
EnableEventHook(void)3590 EnableEventHook(void)
3591 {
3592 #ifdef WAIT_FOR_STDIN
3593     if (PyOS_InputHook == NULL) {
3594 #ifdef WITH_THREAD
3595         event_tstate = PyThreadState_Get();
3596 #endif
3597         PyOS_InputHook = EventHook;
3598     }
3599 #endif
3600 }
3601 
3602 static void
DisableEventHook(void)3603 DisableEventHook(void)
3604 {
3605 #ifdef WAIT_FOR_STDIN
3606     if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3607         PyOS_InputHook = NULL;
3608     }
3609 #endif
3610 }
3611 
3612 
3613 /* all errors will be checked in one fell swoop in init_tkinter() */
3614 static void
ins_long(PyObject * d,char * name,long val)3615 ins_long(PyObject *d, char *name, long val)
3616 {
3617     PyObject *v = PyInt_FromLong(val);
3618     if (v) {
3619         PyDict_SetItemString(d, name, v);
3620         Py_DECREF(v);
3621     }
3622 }
3623 static void
ins_string(PyObject * d,char * name,char * val)3624 ins_string(PyObject *d, char *name, char *val)
3625 {
3626     PyObject *v = PyString_FromString(val);
3627     if (v) {
3628         PyDict_SetItemString(d, name, v);
3629         Py_DECREF(v);
3630     }
3631 }
3632 
3633 
3634 PyMODINIT_FUNC
init_tkinter(void)3635 init_tkinter(void)
3636 {
3637     PyObject *m, *d;
3638 
3639     Py_TYPE(&Tkapp_Type) = &PyType_Type;
3640 
3641 #ifdef WITH_THREAD
3642     tcl_lock = PyThread_allocate_lock();
3643 #endif
3644 
3645     m = Py_InitModule("_tkinter", moduleMethods);
3646     if (m == NULL)
3647         return;
3648 
3649     d = PyModule_GetDict(m);
3650     Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3651     PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3652 
3653     ins_long(d, "READABLE", TCL_READABLE);
3654     ins_long(d, "WRITABLE", TCL_WRITABLE);
3655     ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3656     ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3657     ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3658     ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3659     ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3660     ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3661     ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3662     ins_string(d, "TK_VERSION", TK_VERSION);
3663     ins_string(d, "TCL_VERSION", TCL_VERSION);
3664 
3665     PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3666 
3667     Py_TYPE(&Tktt_Type) = &PyType_Type;
3668     PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3669 
3670     Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3671     PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3672 
3673 #ifdef TK_AQUA
3674     /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3675      * start waking up.  Note that Tcl_FindExecutable will do this, this
3676      * code must be above it! The original warning from
3677      * tkMacOSXAppInit.c is copied below.
3678      *
3679      * NB - You have to swap in the Tk Notifier BEFORE you start up the
3680      * Tcl interpreter for now.  It probably should work to do this
3681      * in the other order, but for now it doesn't seem to.
3682      *
3683      */
3684     Tk_MacOSXSetupTkNotifier();
3685 #endif
3686 
3687 
3688     /* This helps the dynamic loader; in Unicode aware Tcl versions
3689        it also helps Tcl find its encodings. */
3690     Tcl_FindExecutable(Py_GetProgramName());
3691 
3692     if (PyErr_Occurred())
3693         return;
3694 
3695 #if 0
3696     /* This was not a good idea; through <Destroy> bindings,
3697        Tcl_Finalize() may invoke Python code but at that point the
3698        interpreter and thread state have already been destroyed! */
3699     Py_AtExit(Tcl_Finalize);
3700 #endif
3701 
3702 }
3703