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 (_PyAnyInt_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 PyObject *resint = PyNumber_Int(result);
2136 Py_DECREF(result);
2137 return resint;
2138 }
2139
2140 if (PyErr_Occurred())
2141 return NULL;
2142 #else
2143 if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
2144 return PyInt_FromLong(intValue);
2145 #endif
2146 return Tkinter_Error(self);
2147 }
2148
2149 static PyObject *
Tkapp_GetDouble(PyObject * self,PyObject * args)2150 Tkapp_GetDouble(PyObject *self, PyObject *args)
2151 {
2152 char *s;
2153 double v;
2154
2155 if (PyTuple_Size(args) == 1) {
2156 PyObject *o = PyTuple_GetItem(args, 0);
2157 if (PyFloat_Check(o)) {
2158 Py_INCREF(o);
2159 return o;
2160 }
2161 }
2162 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
2163 return NULL;
2164 CHECK_STRING_LENGTH(s);
2165 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2166 return Tkinter_Error(self);
2167 return Py_BuildValue("d", v);
2168 }
2169
2170 static PyObject *
Tkapp_GetBoolean(PyObject * self,PyObject * arg)2171 Tkapp_GetBoolean(PyObject *self, PyObject *arg)
2172 {
2173 char *s;
2174 int v;
2175
2176 if (PyInt_Check(arg)) /* int or bool */
2177 return PyBool_FromLong(PyInt_AS_LONG(arg));
2178
2179 if (PyLong_Check(arg))
2180 return PyBool_FromLong(Py_SIZE(arg) != 0);
2181
2182 if (PyTclObject_Check(arg)) {
2183 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2184 ((PyTclObject*)arg)->value,
2185 &v) == TCL_ERROR)
2186 return Tkinter_Error(self);
2187 return PyBool_FromLong(v);
2188 }
2189
2190 if (!PyArg_Parse(arg, "s:getboolean", &s))
2191 return NULL;
2192 CHECK_STRING_LENGTH(s);
2193 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2194 return Tkinter_Error(self);
2195 return PyBool_FromLong(v);
2196 }
2197
2198 static PyObject *
Tkapp_ExprString(PyObject * self,PyObject * args)2199 Tkapp_ExprString(PyObject *self, PyObject *args)
2200 {
2201 char *s;
2202 PyObject *res = NULL;
2203 int retval;
2204
2205 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
2206 return NULL;
2207
2208 CHECK_STRING_LENGTH(s);
2209 CHECK_TCL_APPARTMENT;
2210
2211 ENTER_TCL
2212 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2213 ENTER_OVERLAP
2214 if (retval == TCL_ERROR)
2215 res = Tkinter_Error(self);
2216 else
2217 res = PyString_FromString(Tkapp_Result(self));
2218 LEAVE_OVERLAP_TCL
2219 return res;
2220 }
2221
2222 static PyObject *
Tkapp_ExprLong(PyObject * self,PyObject * args)2223 Tkapp_ExprLong(PyObject *self, PyObject *args)
2224 {
2225 char *s;
2226 PyObject *res = NULL;
2227 int retval;
2228 long v;
2229
2230 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2231 return NULL;
2232
2233 CHECK_STRING_LENGTH(s);
2234 CHECK_TCL_APPARTMENT;
2235
2236 ENTER_TCL
2237 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2238 ENTER_OVERLAP
2239 if (retval == TCL_ERROR)
2240 res = Tkinter_Error(self);
2241 else
2242 res = Py_BuildValue("l", v);
2243 LEAVE_OVERLAP_TCL
2244 return res;
2245 }
2246
2247 static PyObject *
Tkapp_ExprDouble(PyObject * self,PyObject * args)2248 Tkapp_ExprDouble(PyObject *self, PyObject *args)
2249 {
2250 char *s;
2251 PyObject *res = NULL;
2252 double v;
2253 int retval;
2254
2255 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2256 return NULL;
2257 CHECK_STRING_LENGTH(s);
2258 CHECK_TCL_APPARTMENT;
2259 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2260 ENTER_TCL
2261 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2262 ENTER_OVERLAP
2263 PyFPE_END_PROTECT(retval)
2264 if (retval == TCL_ERROR)
2265 res = Tkinter_Error(self);
2266 else
2267 res = Py_BuildValue("d", v);
2268 LEAVE_OVERLAP_TCL
2269 return res;
2270 }
2271
2272 static PyObject *
Tkapp_ExprBoolean(PyObject * self,PyObject * args)2273 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
2274 {
2275 char *s;
2276 PyObject *res = NULL;
2277 int retval;
2278 int v;
2279
2280 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2281 return NULL;
2282 CHECK_STRING_LENGTH(s);
2283 CHECK_TCL_APPARTMENT;
2284 ENTER_TCL
2285 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2286 ENTER_OVERLAP
2287 if (retval == TCL_ERROR)
2288 res = Tkinter_Error(self);
2289 else
2290 res = Py_BuildValue("i", v);
2291 LEAVE_OVERLAP_TCL
2292 return res;
2293 }
2294
2295
2296
2297 static PyObject *
Tkapp_SplitList(PyObject * self,PyObject * args)2298 Tkapp_SplitList(PyObject *self, PyObject *args)
2299 {
2300 char *list;
2301 int argc;
2302 char **argv;
2303 PyObject *arg, *v;
2304 int i;
2305
2306 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2307 return NULL;
2308 if (PyTclObject_Check(arg)) {
2309 int objc;
2310 Tcl_Obj **objv;
2311 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2312 ((PyTclObject*)arg)->value,
2313 &objc, &objv) == TCL_ERROR) {
2314 return Tkinter_Error(self);
2315 }
2316 if (!(v = PyTuple_New(objc)))
2317 return NULL;
2318 for (i = 0; i < objc; i++) {
2319 PyObject *s = FromObj(self, objv[i]);
2320 if (!s || PyTuple_SetItem(v, i, s)) {
2321 Py_DECREF(v);
2322 return NULL;
2323 }
2324 }
2325 return v;
2326 }
2327 if (PyTuple_Check(arg)) {
2328 Py_INCREF(arg);
2329 return arg;
2330 }
2331
2332 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2333 return NULL;
2334
2335 if (strlen(list) >= INT_MAX) {
2336 PyErr_SetString(PyExc_OverflowError, "string is too long");
2337 PyMem_Free(list);
2338 return NULL;
2339 }
2340 if (Tcl_SplitList(Tkapp_Interp(self), list,
2341 &argc, &argv) == TCL_ERROR) {
2342 PyMem_Free(list);
2343 return Tkinter_Error(self);
2344 }
2345
2346 if (!(v = PyTuple_New(argc)))
2347 goto finally;
2348
2349 for (i = 0; i < argc; i++) {
2350 PyObject *s = PyString_FromString(argv[i]);
2351 if (!s || PyTuple_SetItem(v, i, s)) {
2352 Py_DECREF(v);
2353 v = NULL;
2354 goto finally;
2355 }
2356 }
2357
2358 finally:
2359 ckfree(FREECAST argv);
2360 PyMem_Free(list);
2361 return v;
2362 }
2363
2364 static PyObject *
Tkapp_Split(PyObject * self,PyObject * args)2365 Tkapp_Split(PyObject *self, PyObject *args)
2366 {
2367 PyObject *arg, *v;
2368 char *list;
2369
2370 if (!PyArg_ParseTuple(args, "O:split", &arg))
2371 return NULL;
2372 if (PyTclObject_Check(arg)) {
2373 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2374 int objc;
2375 Tcl_Obj **objv;
2376 int i;
2377 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2378 &objc, &objv) == TCL_ERROR) {
2379 return FromObj(self, value);
2380 }
2381 if (objc == 0)
2382 return PyString_FromString("");
2383 if (objc == 1)
2384 return FromObj(self, objv[0]);
2385 if (!(v = PyTuple_New(objc)))
2386 return NULL;
2387 for (i = 0; i < objc; i++) {
2388 PyObject *s = FromObj(self, objv[i]);
2389 if (!s || PyTuple_SetItem(v, i, s)) {
2390 Py_DECREF(v);
2391 return NULL;
2392 }
2393 }
2394 return v;
2395 }
2396 if (PyTuple_Check(arg))
2397 return SplitObj(arg);
2398
2399 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2400 return NULL;
2401 if (strlen(list) >= INT_MAX) {
2402 PyErr_SetString(PyExc_OverflowError, "string is too long");
2403 PyMem_Free(list);
2404 return NULL;
2405 }
2406 v = Split(list);
2407 PyMem_Free(list);
2408 return v;
2409 }
2410
2411 static PyObject *
Tkapp_Merge(PyObject * self,PyObject * args)2412 Tkapp_Merge(PyObject *self, PyObject *args)
2413 {
2414 char *s = Merge(args);
2415 PyObject *res = NULL;
2416
2417 if (s) {
2418 res = PyString_FromString(s);
2419 ckfree(s);
2420 }
2421
2422 return res;
2423 }
2424
2425
2426
2427 /** Tcl Command **/
2428
2429 /* Client data struct */
2430 typedef struct {
2431 PyObject *self;
2432 PyObject *func;
2433 } PythonCmd_ClientData;
2434
2435 static int
PythonCmd_Error(Tcl_Interp * interp)2436 PythonCmd_Error(Tcl_Interp *interp)
2437 {
2438 errorInCmd = 1;
2439 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2440 LEAVE_PYTHON
2441 return TCL_ERROR;
2442 }
2443
2444 /* This is the Tcl command that acts as a wrapper for Python
2445 * function or method.
2446 */
2447 static int
PythonCmd(ClientData clientData,Tcl_Interp * interp,int argc,char * argv[])2448 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2449 {
2450 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2451 PyObject *func, *arg, *res;
2452 int i, rv;
2453 Tcl_Obj *obj_res;
2454
2455 ENTER_PYTHON
2456
2457 /* TBD: no error checking here since we know, via the
2458 * Tkapp_CreateCommand() that the client data is a two-tuple
2459 */
2460 func = data->func;
2461
2462 /* Create argument list (argv1, ..., argvN) */
2463 if (!(arg = PyTuple_New(argc - 1)))
2464 return PythonCmd_Error(interp);
2465
2466 for (i = 0; i < (argc - 1); i++) {
2467 PyObject *s = fromTclString(argv[i + 1]);
2468 if (!s || PyTuple_SetItem(arg, i, s)) {
2469 Py_DECREF(arg);
2470 return PythonCmd_Error(interp);
2471 }
2472 }
2473 res = PyEval_CallObject(func, arg);
2474 Py_DECREF(arg);
2475
2476 if (res == NULL)
2477 return PythonCmd_Error(interp);
2478
2479 obj_res = AsObj(res);
2480 if (obj_res == NULL) {
2481 Py_DECREF(res);
2482 return PythonCmd_Error(interp);
2483 }
2484 else {
2485 Tcl_SetObjResult(interp, obj_res);
2486 rv = TCL_OK;
2487 }
2488
2489 Py_DECREF(res);
2490
2491 LEAVE_PYTHON
2492
2493 return rv;
2494 }
2495
2496 static void
PythonCmdDelete(ClientData clientData)2497 PythonCmdDelete(ClientData clientData)
2498 {
2499 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2500
2501 ENTER_PYTHON
2502 Py_XDECREF(data->self);
2503 Py_XDECREF(data->func);
2504 PyMem_DEL(data);
2505 LEAVE_PYTHON
2506 }
2507
2508
2509
2510
2511 #ifdef WITH_THREAD
2512 TCL_DECLARE_MUTEX(command_mutex)
2513
2514 typedef struct CommandEvent{
2515 Tcl_Event ev;
2516 Tcl_Interp* interp;
2517 char *name;
2518 int create;
2519 int *status;
2520 ClientData *data;
2521 Tcl_Condition *done;
2522 } CommandEvent;
2523
2524 static int
Tkapp_CommandProc(CommandEvent * ev,int flags)2525 Tkapp_CommandProc(CommandEvent *ev, int flags)
2526 {
2527 if (ev->create)
2528 *ev->status = Tcl_CreateCommand(
2529 ev->interp, ev->name, PythonCmd,
2530 ev->data, PythonCmdDelete) == NULL;
2531 else
2532 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2533 Tcl_MutexLock(&command_mutex);
2534 Tcl_ConditionNotify(ev->done);
2535 Tcl_MutexUnlock(&command_mutex);
2536 return 1;
2537 }
2538 #endif
2539
2540 static PyObject *
Tkapp_CreateCommand(PyObject * selfptr,PyObject * args)2541 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2542 {
2543 TkappObject *self = (TkappObject*)selfptr;
2544 PythonCmd_ClientData *data;
2545 char *cmdName;
2546 PyObject *func;
2547 int err;
2548
2549 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2550 return NULL;
2551 CHECK_STRING_LENGTH(cmdName);
2552 if (!PyCallable_Check(func)) {
2553 PyErr_SetString(PyExc_TypeError, "command not callable");
2554 return NULL;
2555 }
2556
2557 #ifdef WITH_THREAD
2558 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2559 !WaitForMainloop(self))
2560 return NULL;
2561 #endif
2562
2563 data = PyMem_NEW(PythonCmd_ClientData, 1);
2564 if (!data)
2565 return PyErr_NoMemory();
2566 Py_INCREF(self);
2567 Py_INCREF(func);
2568 data->self = selfptr;
2569 data->func = func;
2570
2571 #ifdef WITH_THREAD
2572 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2573 Tcl_Condition cond = NULL;
2574 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2575 if (ev == NULL) {
2576 PyErr_NoMemory();
2577 PyMem_DEL(data);
2578 return NULL;
2579 }
2580 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2581 ev->interp = self->interp;
2582 ev->create = 1;
2583 ev->name = cmdName;
2584 ev->data = (ClientData)data;
2585 ev->status = &err;
2586 ev->done = &cond;
2587 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2588 Tcl_ConditionFinalize(&cond);
2589 }
2590 else
2591 #endif
2592 {
2593 ENTER_TCL
2594 err = Tcl_CreateCommand(
2595 Tkapp_Interp(self), cmdName, PythonCmd,
2596 (ClientData)data, PythonCmdDelete) == NULL;
2597 LEAVE_TCL
2598 }
2599 if (err) {
2600 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2601 PyMem_DEL(data);
2602 return NULL;
2603 }
2604
2605 Py_INCREF(Py_None);
2606 return Py_None;
2607 }
2608
2609
2610
2611 static PyObject *
Tkapp_DeleteCommand(PyObject * selfptr,PyObject * args)2612 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2613 {
2614 TkappObject *self = (TkappObject*)selfptr;
2615 char *cmdName;
2616 int err;
2617
2618 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2619 return NULL;
2620 CHECK_STRING_LENGTH(cmdName);
2621
2622 #ifdef WITH_THREAD
2623 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2624 Tcl_Condition cond = NULL;
2625 CommandEvent *ev;
2626 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2627 if (ev == NULL) {
2628 PyErr_NoMemory();
2629 return NULL;
2630 }
2631 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2632 ev->interp = self->interp;
2633 ev->create = 0;
2634 ev->name = cmdName;
2635 ev->status = &err;
2636 ev->done = &cond;
2637 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2638 &command_mutex);
2639 Tcl_ConditionFinalize(&cond);
2640 }
2641 else
2642 #endif
2643 {
2644 ENTER_TCL
2645 err = Tcl_DeleteCommand(self->interp, cmdName);
2646 LEAVE_TCL
2647 }
2648 if (err == -1) {
2649 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2650 return NULL;
2651 }
2652 Py_INCREF(Py_None);
2653 return Py_None;
2654 }
2655
2656
2657
2658 #ifdef HAVE_CREATEFILEHANDLER
2659 /** File Handler **/
2660
2661 typedef struct _fhcdata {
2662 PyObject *func;
2663 PyObject *file;
2664 int id;
2665 struct _fhcdata *next;
2666 } FileHandler_ClientData;
2667
2668 static FileHandler_ClientData *HeadFHCD;
2669
2670 static FileHandler_ClientData *
NewFHCD(PyObject * func,PyObject * file,int id)2671 NewFHCD(PyObject *func, PyObject *file, int id)
2672 {
2673 FileHandler_ClientData *p;
2674 p = PyMem_NEW(FileHandler_ClientData, 1);
2675 if (p != NULL) {
2676 Py_XINCREF(func);
2677 Py_XINCREF(file);
2678 p->func = func;
2679 p->file = file;
2680 p->id = id;
2681 p->next = HeadFHCD;
2682 HeadFHCD = p;
2683 }
2684 return p;
2685 }
2686
2687 static void
DeleteFHCD(int id)2688 DeleteFHCD(int id)
2689 {
2690 FileHandler_ClientData *p, **pp;
2691
2692 pp = &HeadFHCD;
2693 while ((p = *pp) != NULL) {
2694 if (p->id == id) {
2695 *pp = p->next;
2696 Py_XDECREF(p->func);
2697 Py_XDECREF(p->file);
2698 PyMem_DEL(p);
2699 }
2700 else
2701 pp = &p->next;
2702 }
2703 }
2704
2705 static void
FileHandler(ClientData clientData,int mask)2706 FileHandler(ClientData clientData, int mask)
2707 {
2708 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2709 PyObject *func, *file, *arg, *res;
2710
2711 ENTER_PYTHON
2712 func = data->func;
2713 file = data->file;
2714
2715 arg = Py_BuildValue("(Oi)", file, (long) mask);
2716 res = PyEval_CallObject(func, arg);
2717 Py_DECREF(arg);
2718
2719 if (res == NULL) {
2720 errorInCmd = 1;
2721 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2722 }
2723 Py_XDECREF(res);
2724 LEAVE_PYTHON
2725 }
2726
2727 static PyObject *
Tkapp_CreateFileHandler(PyObject * self,PyObject * args)2728 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2729 /* args is (file, mask, func) */
2730 {
2731 FileHandler_ClientData *data;
2732 PyObject *file, *func;
2733 int mask, tfile;
2734
2735 if (!self && Py_Py3kWarningFlag) {
2736 if (PyErr_Warn(PyExc_DeprecationWarning,
2737 "_tkinter.createfilehandler is gone in 3.x") < 0)
2738 return NULL;
2739 }
2740
2741 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2742 &file, &mask, &func))
2743 return NULL;
2744
2745 #ifdef WITH_THREAD
2746 if (!self && !tcl_lock) {
2747 /* We don't have the Tcl lock since Tcl is threaded. */
2748 PyErr_SetString(PyExc_RuntimeError,
2749 "_tkinter.createfilehandler not supported "
2750 "for threaded Tcl");
2751 return NULL;
2752 }
2753 #endif
2754
2755 if (self) {
2756 CHECK_TCL_APPARTMENT;
2757 }
2758
2759 tfile = PyObject_AsFileDescriptor(file);
2760 if (tfile < 0)
2761 return NULL;
2762 if (!PyCallable_Check(func)) {
2763 PyErr_SetString(PyExc_TypeError, "bad argument list");
2764 return NULL;
2765 }
2766
2767 data = NewFHCD(func, file, tfile);
2768 if (data == NULL)
2769 return NULL;
2770
2771 /* Ought to check for null Tcl_File object... */
2772 ENTER_TCL
2773 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2774 LEAVE_TCL
2775 Py_INCREF(Py_None);
2776 return Py_None;
2777 }
2778
2779 static PyObject *
Tkapp_DeleteFileHandler(PyObject * self,PyObject * args)2780 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2781 {
2782 PyObject *file;
2783 int tfile;
2784
2785 if (!self && Py_Py3kWarningFlag) {
2786 if (PyErr_Warn(PyExc_DeprecationWarning,
2787 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2788 return NULL;
2789 }
2790
2791 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2792 return NULL;
2793
2794 #ifdef WITH_THREAD
2795 if (!self && !tcl_lock) {
2796 /* We don't have the Tcl lock since Tcl is threaded. */
2797 PyErr_SetString(PyExc_RuntimeError,
2798 "_tkinter.deletefilehandler not supported "
2799 "for threaded Tcl");
2800 return NULL;
2801 }
2802 #endif
2803
2804 if (self) {
2805 CHECK_TCL_APPARTMENT;
2806 }
2807
2808 tfile = PyObject_AsFileDescriptor(file);
2809 if (tfile < 0)
2810 return NULL;
2811
2812 DeleteFHCD(tfile);
2813
2814 /* Ought to check for null Tcl_File object... */
2815 ENTER_TCL
2816 Tcl_DeleteFileHandler(tfile);
2817 LEAVE_TCL
2818 Py_INCREF(Py_None);
2819 return Py_None;
2820 }
2821 #endif /* HAVE_CREATEFILEHANDLER */
2822
2823
2824 /**** Tktt Object (timer token) ****/
2825
2826 static PyTypeObject Tktt_Type;
2827
2828 typedef struct {
2829 PyObject_HEAD
2830 Tcl_TimerToken token;
2831 PyObject *func;
2832 } TkttObject;
2833
2834 static PyObject *
Tktt_DeleteTimerHandler(PyObject * self,PyObject * args)2835 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2836 {
2837 TkttObject *v = (TkttObject *)self;
2838 PyObject *func = v->func;
2839
2840 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2841 return NULL;
2842 if (v->token != NULL) {
2843 Tcl_DeleteTimerHandler(v->token);
2844 v->token = NULL;
2845 }
2846 if (func != NULL) {
2847 v->func = NULL;
2848 Py_DECREF(func);
2849 Py_DECREF(v); /* See Tktt_New() */
2850 }
2851 Py_INCREF(Py_None);
2852 return Py_None;
2853 }
2854
2855 static PyMethodDef Tktt_methods[] =
2856 {
2857 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2858 {NULL, NULL}
2859 };
2860
2861 static TkttObject *
Tktt_New(PyObject * func)2862 Tktt_New(PyObject *func)
2863 {
2864 TkttObject *v;
2865
2866 v = PyObject_New(TkttObject, &Tktt_Type);
2867 if (v == NULL)
2868 return NULL;
2869
2870 Py_INCREF(func);
2871 v->token = NULL;
2872 v->func = func;
2873
2874 /* Extra reference, deleted when called or when handler is deleted */
2875 Py_INCREF(v);
2876 return v;
2877 }
2878
2879 static void
Tktt_Dealloc(PyObject * self)2880 Tktt_Dealloc(PyObject *self)
2881 {
2882 TkttObject *v = (TkttObject *)self;
2883 PyObject *func = v->func;
2884
2885 Py_XDECREF(func);
2886
2887 PyObject_Del(self);
2888 }
2889
2890 static PyObject *
Tktt_Repr(PyObject * self)2891 Tktt_Repr(PyObject *self)
2892 {
2893 TkttObject *v = (TkttObject *)self;
2894 char buf[100];
2895
2896 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2897 v->func == NULL ? ", handler deleted" : "");
2898 return PyString_FromString(buf);
2899 }
2900
2901 static PyObject *
Tktt_GetAttr(PyObject * self,char * name)2902 Tktt_GetAttr(PyObject *self, char *name)
2903 {
2904 return Py_FindMethod(Tktt_methods, self, name);
2905 }
2906
2907 static PyTypeObject Tktt_Type =
2908 {
2909 PyVarObject_HEAD_INIT(NULL, 0)
2910 "tktimertoken", /*tp_name */
2911 sizeof(TkttObject), /*tp_basicsize */
2912 0, /*tp_itemsize */
2913 Tktt_Dealloc, /*tp_dealloc */
2914 0, /*tp_print */
2915 Tktt_GetAttr, /*tp_getattr */
2916 0, /*tp_setattr */
2917 0, /*tp_compare */
2918 Tktt_Repr, /*tp_repr */
2919 0, /*tp_as_number */
2920 0, /*tp_as_sequence */
2921 0, /*tp_as_mapping */
2922 0, /*tp_hash */
2923 };
2924
2925
2926
2927 /** Timer Handler **/
2928
2929 static void
TimerHandler(ClientData clientData)2930 TimerHandler(ClientData clientData)
2931 {
2932 TkttObject *v = (TkttObject *)clientData;
2933 PyObject *func = v->func;
2934 PyObject *res;
2935
2936 if (func == NULL)
2937 return;
2938
2939 v->func = NULL;
2940
2941 ENTER_PYTHON
2942
2943 res = PyEval_CallObject(func, NULL);
2944 Py_DECREF(func);
2945 Py_DECREF(v); /* See Tktt_New() */
2946
2947 if (res == NULL) {
2948 errorInCmd = 1;
2949 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2950 }
2951 else
2952 Py_DECREF(res);
2953
2954 LEAVE_PYTHON
2955 }
2956
2957 static PyObject *
Tkapp_CreateTimerHandler(PyObject * self,PyObject * args)2958 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2959 {
2960 int milliseconds;
2961 PyObject *func;
2962 TkttObject *v;
2963
2964 if (!self && Py_Py3kWarningFlag) {
2965 if (PyErr_Warn(PyExc_DeprecationWarning,
2966 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2967 return NULL;
2968 }
2969
2970 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2971 &milliseconds, &func))
2972 return NULL;
2973 if (!PyCallable_Check(func)) {
2974 PyErr_SetString(PyExc_TypeError, "bad argument list");
2975 return NULL;
2976 }
2977
2978 #ifdef WITH_THREAD
2979 if (!self && !tcl_lock) {
2980 /* We don't have the Tcl lock since Tcl is threaded. */
2981 PyErr_SetString(PyExc_RuntimeError,
2982 "_tkinter.createtimerhandler not supported "
2983 "for threaded Tcl");
2984 return NULL;
2985 }
2986 #endif
2987
2988 if (self) {
2989 CHECK_TCL_APPARTMENT;
2990 }
2991
2992 v = Tktt_New(func);
2993 if (v) {
2994 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2995 (ClientData)v);
2996 }
2997
2998 return (PyObject *) v;
2999 }
3000
3001
3002 /** Event Loop **/
3003
3004 static PyObject *
Tkapp_MainLoop(PyObject * selfptr,PyObject * args)3005 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
3006 {
3007 int threshold = 0;
3008 TkappObject *self = (TkappObject*)selfptr;
3009 #ifdef WITH_THREAD
3010 PyThreadState *tstate = PyThreadState_Get();
3011 #endif
3012
3013 if (!self && Py_Py3kWarningFlag) {
3014 if (PyErr_Warn(PyExc_DeprecationWarning,
3015 "_tkinter.mainloop is gone in 3.x") < 0)
3016 return NULL;
3017 }
3018
3019 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
3020 return NULL;
3021
3022 #ifdef WITH_THREAD
3023 if (!self && !tcl_lock) {
3024 /* We don't have the Tcl lock since Tcl is threaded. */
3025 PyErr_SetString(PyExc_RuntimeError,
3026 "_tkinter.mainloop not supported "
3027 "for threaded Tcl");
3028 return NULL;
3029 }
3030 #endif
3031
3032 if (self) {
3033 CHECK_TCL_APPARTMENT;
3034 self->dispatching = 1;
3035 }
3036
3037 quitMainLoop = 0;
3038 while (Tk_GetNumMainWindows() > threshold &&
3039 !quitMainLoop &&
3040 !errorInCmd)
3041 {
3042 int result;
3043
3044 #ifdef WITH_THREAD
3045 if (self && self->threaded) {
3046 /* Allow other Python threads to run. */
3047 ENTER_TCL
3048 result = Tcl_DoOneEvent(0);
3049 LEAVE_TCL
3050 }
3051 else {
3052 Py_BEGIN_ALLOW_THREADS
3053 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3054 tcl_tstate = tstate;
3055 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3056 tcl_tstate = NULL;
3057 if(tcl_lock)PyThread_release_lock(tcl_lock);
3058 if (result == 0)
3059 Sleep(Tkinter_busywaitinterval);
3060 Py_END_ALLOW_THREADS
3061 }
3062 #else
3063 result = Tcl_DoOneEvent(0);
3064 #endif
3065
3066 if (PyErr_CheckSignals() != 0) {
3067 if (self)
3068 self->dispatching = 0;
3069 return NULL;
3070 }
3071 if (result < 0)
3072 break;
3073 }
3074 if (self)
3075 self->dispatching = 0;
3076 quitMainLoop = 0;
3077
3078 if (errorInCmd) {
3079 errorInCmd = 0;
3080 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3081 excInCmd = valInCmd = trbInCmd = NULL;
3082 return NULL;
3083 }
3084 Py_INCREF(Py_None);
3085 return Py_None;
3086 }
3087
3088 static PyObject *
Tkapp_DoOneEvent(PyObject * self,PyObject * args)3089 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
3090 {
3091 int flags = 0;
3092 int rv;
3093
3094 if (!self && Py_Py3kWarningFlag) {
3095 if (PyErr_Warn(PyExc_DeprecationWarning,
3096 "_tkinter.dooneevent is gone in 3.x") < 0)
3097 return NULL;
3098 }
3099
3100 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
3101 return NULL;
3102
3103 ENTER_TCL
3104 rv = Tcl_DoOneEvent(flags);
3105 LEAVE_TCL
3106 return Py_BuildValue("i", rv);
3107 }
3108
3109 static PyObject *
Tkapp_Quit(PyObject * self,PyObject * args)3110 Tkapp_Quit(PyObject *self, PyObject *args)
3111 {
3112
3113 if (!self && Py_Py3kWarningFlag) {
3114 if (PyErr_Warn(PyExc_DeprecationWarning,
3115 "_tkinter.quit is gone in 3.x") < 0)
3116 return NULL;
3117 }
3118
3119 if (!PyArg_ParseTuple(args, ":quit"))
3120 return NULL;
3121
3122 quitMainLoop = 1;
3123 Py_INCREF(Py_None);
3124 return Py_None;
3125 }
3126
3127 static PyObject *
Tkapp_InterpAddr(PyObject * self,PyObject * args)3128 Tkapp_InterpAddr(PyObject *self, PyObject *args)
3129 {
3130
3131 if (!PyArg_ParseTuple(args, ":interpaddr"))
3132 return NULL;
3133
3134 return PyLong_FromVoidPtr(Tkapp_Interp(self));
3135 }
3136
3137 static PyObject *
Tkapp_TkInit(PyObject * self,PyObject * args)3138 Tkapp_TkInit(PyObject *self, PyObject *args)
3139 {
3140 Tcl_Interp *interp = Tkapp_Interp(self);
3141 const char * _tk_exists = NULL;
3142 int err;
3143
3144 #ifdef TKINTER_PROTECT_LOADTK
3145 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3146 * first call failed.
3147 * To avoid the deadlock, we just refuse the second call through
3148 * a static variable.
3149 */
3150 if (tk_load_failed) {
3151 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3152 return NULL;
3153 }
3154 #endif
3155
3156 /* We want to guard against calling Tk_Init() multiple times */
3157 CHECK_TCL_APPARTMENT;
3158 ENTER_TCL
3159 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3160 ENTER_OVERLAP
3161 if (err == TCL_ERROR) {
3162 /* This sets an exception, but we cannot return right
3163 away because we need to exit the overlap first. */
3164 Tkinter_Error(self);
3165 } else {
3166 _tk_exists = Tkapp_Result(self);
3167 }
3168 LEAVE_OVERLAP_TCL
3169 if (err == TCL_ERROR) {
3170 return NULL;
3171 }
3172 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3173 if (Tk_Init(interp) == TCL_ERROR) {
3174 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
3175 #ifdef TKINTER_PROTECT_LOADTK
3176 tk_load_failed = 1;
3177 #endif
3178 return NULL;
3179 }
3180 }
3181 Py_INCREF(Py_None);
3182 return Py_None;
3183 }
3184
3185 static PyObject *
Tkapp_WantObjects(PyObject * self,PyObject * args)3186 Tkapp_WantObjects(PyObject *self, PyObject *args)
3187 {
3188
3189 int wantobjects = -1;
3190 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3191 return NULL;
3192 if (wantobjects == -1)
3193 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3194 ((TkappObject*)self)->wantobjects = wantobjects;
3195
3196 Py_INCREF(Py_None);
3197 return Py_None;
3198 }
3199
3200 static PyObject *
Tkapp_WillDispatch(PyObject * self,PyObject * args)3201 Tkapp_WillDispatch(PyObject *self, PyObject *args)
3202 {
3203
3204 ((TkappObject*)self)->dispatching = 1;
3205
3206 Py_INCREF(Py_None);
3207 return Py_None;
3208 }
3209
3210 /* Convert Python string or any buffer compatible object to Tcl byte-array
3211 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
3212 */
3213 static PyObject *
Tkapp_CreateByteArray(PyObject * self,PyObject * args)3214 Tkapp_CreateByteArray(PyObject *self, PyObject *args)
3215 {
3216 Py_buffer view;
3217 Tcl_Obj* obj;
3218 PyObject *res = NULL;
3219
3220 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
3221 return NULL;
3222
3223 if (view.len >= INT_MAX) {
3224 PyErr_SetString(PyExc_OverflowError, "string is too long");
3225 return NULL;
3226 }
3227 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
3228 if (obj == NULL) {
3229 PyBuffer_Release(&view);
3230 return Tkinter_Error(self);
3231 }
3232 res = newPyTclObject(obj);
3233 PyBuffer_Release(&view);
3234 return res;
3235 }
3236
3237
3238 /**** Tkapp Method List ****/
3239
3240 static PyMethodDef Tkapp_methods[] =
3241 {
3242 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
3243 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3244 {"call", Tkapp_Call, METH_VARARGS},
3245 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
3246 {"eval", Tkapp_Eval, METH_VARARGS},
3247 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3248 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3249 {"record", Tkapp_Record, METH_VARARGS},
3250 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3251 {"setvar", Tkapp_SetVar, METH_VARARGS},
3252 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3253 {"getvar", Tkapp_GetVar, METH_VARARGS},
3254 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3255 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3256 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3257 {"getint", Tkapp_GetInt, METH_VARARGS},
3258 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
3259 {"getboolean", Tkapp_GetBoolean, METH_O},
3260 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3261 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3262 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3263 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3264 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3265 {"split", Tkapp_Split, METH_VARARGS},
3266 {"merge", Tkapp_Merge, METH_VARARGS},
3267 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3268 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
3269 #ifdef HAVE_CREATEFILEHANDLER
3270 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3271 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
3272 #endif
3273 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3274 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3275 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3276 {"quit", Tkapp_Quit, METH_VARARGS},
3277 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3278 {"loadtk", Tkapp_TkInit, METH_NOARGS},
3279 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
3280 {NULL, NULL}
3281 };
3282
3283
3284
3285 /**** Tkapp Type Methods ****/
3286
3287 static void
Tkapp_Dealloc(PyObject * self)3288 Tkapp_Dealloc(PyObject *self)
3289 {
3290 /*CHECK_TCL_APPARTMENT;*/
3291 ENTER_TCL
3292 Tcl_DeleteInterp(Tkapp_Interp(self));
3293 LEAVE_TCL
3294 PyObject_Del(self);
3295 DisableEventHook();
3296 }
3297
3298 static PyObject *
Tkapp_GetAttr(PyObject * self,char * name)3299 Tkapp_GetAttr(PyObject *self, char *name)
3300 {
3301 return Py_FindMethod(Tkapp_methods, self, name);
3302 }
3303
3304 static PyTypeObject Tkapp_Type =
3305 {
3306 PyVarObject_HEAD_INIT(NULL, 0)
3307 "tkapp", /*tp_name */
3308 sizeof(TkappObject), /*tp_basicsize */
3309 0, /*tp_itemsize */
3310 Tkapp_Dealloc, /*tp_dealloc */
3311 0, /*tp_print */
3312 Tkapp_GetAttr, /*tp_getattr */
3313 0, /*tp_setattr */
3314 0, /*tp_compare */
3315 0, /*tp_repr */
3316 0, /*tp_as_number */
3317 0, /*tp_as_sequence */
3318 0, /*tp_as_mapping */
3319 0, /*tp_hash */
3320 };
3321
3322
3323
3324 /**** Tkinter Module ****/
3325
3326 typedef struct {
3327 PyObject* tuple;
3328 int size; /* current size */
3329 int maxsize; /* allocated size */
3330 } FlattenContext;
3331
3332 static int
_bump(FlattenContext * context,int size)3333 _bump(FlattenContext* context, int size)
3334 {
3335 /* expand tuple to hold (at least) size new items.
3336 return true if successful, false if an exception was raised */
3337
3338 int maxsize = context->maxsize * 2;
3339
3340 if (maxsize < context->size + size)
3341 maxsize = context->size + size;
3342
3343 context->maxsize = maxsize;
3344
3345 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
3346 }
3347
3348 static int
_flatten1(FlattenContext * context,PyObject * item,int depth)3349 _flatten1(FlattenContext* context, PyObject* item, int depth)
3350 {
3351 /* add tuple or list to argument tuple (recursively) */
3352
3353 int i, size;
3354
3355 if (depth > 1000) {
3356 PyErr_SetString(PyExc_ValueError,
3357 "nesting too deep in _flatten");
3358 return 0;
3359 } else if (PyList_Check(item)) {
3360 size = PyList_GET_SIZE(item);
3361 /* preallocate (assume no nesting) */
3362 if (context->size + size > context->maxsize &&
3363 !_bump(context, size))
3364 return 0;
3365 /* copy items to output tuple */
3366 for (i = 0; i < size; i++) {
3367 PyObject *o = PyList_GET_ITEM(item, i);
3368 if (PyList_Check(o) || PyTuple_Check(o)) {
3369 if (!_flatten1(context, o, depth + 1))
3370 return 0;
3371 } else if (o != Py_None) {
3372 if (context->size + 1 > context->maxsize &&
3373 !_bump(context, 1))
3374 return 0;
3375 Py_INCREF(o);
3376 PyTuple_SET_ITEM(context->tuple,
3377 context->size++, o);
3378 }
3379 }
3380 } else if (PyTuple_Check(item)) {
3381 /* same, for tuples */
3382 size = PyTuple_GET_SIZE(item);
3383 if (context->size + size > context->maxsize &&
3384 !_bump(context, size))
3385 return 0;
3386 for (i = 0; i < size; i++) {
3387 PyObject *o = PyTuple_GET_ITEM(item, i);
3388 if (PyList_Check(o) || PyTuple_Check(o)) {
3389 if (!_flatten1(context, o, depth + 1))
3390 return 0;
3391 } else if (o != Py_None) {
3392 if (context->size + 1 > context->maxsize &&
3393 !_bump(context, 1))
3394 return 0;
3395 Py_INCREF(o);
3396 PyTuple_SET_ITEM(context->tuple,
3397 context->size++, o);
3398 }
3399 }
3400 } else {
3401 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3402 return 0;
3403 }
3404 return 1;
3405 }
3406
3407 static PyObject *
Tkinter_Flatten(PyObject * self,PyObject * args)3408 Tkinter_Flatten(PyObject* self, PyObject* args)
3409 {
3410 FlattenContext context;
3411 PyObject* item;
3412
3413 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3414 return NULL;
3415
3416 context.maxsize = PySequence_Size(item);
3417 if (context.maxsize < 0)
3418 return NULL;
3419 if (context.maxsize == 0)
3420 return PyTuple_New(0);
3421
3422 context.tuple = PyTuple_New(context.maxsize);
3423 if (!context.tuple)
3424 return NULL;
3425
3426 context.size = 0;
3427
3428 if (!_flatten1(&context, item,0))
3429 return NULL;
3430
3431 if (_PyTuple_Resize(&context.tuple, context.size))
3432 return NULL;
3433
3434 return context.tuple;
3435 }
3436
3437 static PyObject *
Tkinter_Create(PyObject * self,PyObject * args)3438 Tkinter_Create(PyObject *self, PyObject *args)
3439 {
3440 char *screenName = NULL;
3441 char *baseName = NULL;
3442 char *className = NULL;
3443 int interactive = 0;
3444 int wantobjects = 0;
3445 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3446 int sync = 0; /* pass -sync to wish */
3447 char *use = NULL; /* pass -use to wish */
3448
3449 baseName = strrchr(Py_GetProgramName(), '/');
3450 if (baseName != NULL)
3451 baseName++;
3452 else
3453 baseName = Py_GetProgramName();
3454 className = "Tk";
3455
3456 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3457 &screenName, &baseName, &className,
3458 &interactive, &wantobjects, &wantTk,
3459 &sync, &use))
3460 return NULL;
3461 CHECK_STRING_LENGTH(screenName);
3462 CHECK_STRING_LENGTH(baseName);
3463 CHECK_STRING_LENGTH(className);
3464 CHECK_STRING_LENGTH(use);
3465
3466 return (PyObject *) Tkapp_New(screenName, baseName, className,
3467 interactive, wantobjects, wantTk,
3468 sync, use);
3469 }
3470
3471 static PyObject *
Tkinter_setbusywaitinterval(PyObject * self,PyObject * args)3472 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3473 {
3474 int new_val;
3475 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3476 return NULL;
3477 if (new_val < 0) {
3478 PyErr_SetString(PyExc_ValueError,
3479 "busywaitinterval must be >= 0");
3480 return NULL;
3481 }
3482 Tkinter_busywaitinterval = new_val;
3483 Py_INCREF(Py_None);
3484 return Py_None;
3485 }
3486
3487 static char setbusywaitinterval_doc[] =
3488 "setbusywaitinterval(n) -> None\n\
3489 \n\
3490 Set the busy-wait interval in milliseconds between successive\n\
3491 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3492 It should be set to a divisor of the maximum time between\n\
3493 frames in an animation.";
3494
3495 static PyObject *
Tkinter_getbusywaitinterval(PyObject * self,PyObject * args)3496 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3497 {
3498 return PyInt_FromLong(Tkinter_busywaitinterval);
3499 }
3500
3501 static char getbusywaitinterval_doc[] =
3502 "getbusywaitinterval() -> int\n\
3503 \n\
3504 Return the current busy-wait interval between successive\n\
3505 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3506
3507 static PyMethodDef moduleMethods[] =
3508 {
3509 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3510 {"create", Tkinter_Create, METH_VARARGS},
3511 #ifdef HAVE_CREATEFILEHANDLER
3512 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3513 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
3514 #endif
3515 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3516 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3517 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3518 {"quit", Tkapp_Quit, METH_VARARGS},
3519 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3520 setbusywaitinterval_doc},
3521 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3522 METH_NOARGS, getbusywaitinterval_doc},
3523 {NULL, NULL}
3524 };
3525
3526 #ifdef WAIT_FOR_STDIN
3527
3528 static int stdin_ready = 0;
3529
3530 #ifndef MS_WINDOWS
3531 static void
MyFileProc(void * clientData,int mask)3532 MyFileProc(void *clientData, int mask)
3533 {
3534 stdin_ready = 1;
3535 }
3536 #endif
3537
3538 #ifdef WITH_THREAD
3539 static PyThreadState *event_tstate = NULL;
3540 #endif
3541
3542 static int
EventHook(void)3543 EventHook(void)
3544 {
3545 #ifndef MS_WINDOWS
3546 int tfile;
3547 #endif
3548 #ifdef WITH_THREAD
3549 PyEval_RestoreThread(event_tstate);
3550 #endif
3551 stdin_ready = 0;
3552 errorInCmd = 0;
3553 #ifndef MS_WINDOWS
3554 tfile = fileno(stdin);
3555 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3556 #endif
3557 while (!errorInCmd && !stdin_ready) {
3558 int result;
3559 #ifdef MS_WINDOWS
3560 if (_kbhit()) {
3561 stdin_ready = 1;
3562 break;
3563 }
3564 #endif
3565 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3566 Py_BEGIN_ALLOW_THREADS
3567 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3568 tcl_tstate = event_tstate;
3569
3570 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3571
3572 tcl_tstate = NULL;
3573 if(tcl_lock)PyThread_release_lock(tcl_lock);
3574 if (result == 0)
3575 Sleep(Tkinter_busywaitinterval);
3576 Py_END_ALLOW_THREADS
3577 #else
3578 result = Tcl_DoOneEvent(0);
3579 #endif
3580
3581 if (result < 0)
3582 break;
3583 }
3584 #ifndef MS_WINDOWS
3585 Tcl_DeleteFileHandler(tfile);
3586 #endif
3587 if (errorInCmd) {
3588 errorInCmd = 0;
3589 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3590 excInCmd = valInCmd = trbInCmd = NULL;
3591 PyErr_Print();
3592 }
3593 #ifdef WITH_THREAD
3594 PyEval_SaveThread();
3595 #endif
3596 return 0;
3597 }
3598
3599 #endif
3600
3601 static void
EnableEventHook(void)3602 EnableEventHook(void)
3603 {
3604 #ifdef WAIT_FOR_STDIN
3605 if (PyOS_InputHook == NULL) {
3606 #ifdef WITH_THREAD
3607 event_tstate = PyThreadState_Get();
3608 #endif
3609 PyOS_InputHook = EventHook;
3610 }
3611 #endif
3612 }
3613
3614 static void
DisableEventHook(void)3615 DisableEventHook(void)
3616 {
3617 #ifdef WAIT_FOR_STDIN
3618 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3619 PyOS_InputHook = NULL;
3620 }
3621 #endif
3622 }
3623
3624
3625 /* all errors will be checked in one fell swoop in init_tkinter() */
3626 static void
ins_long(PyObject * d,char * name,long val)3627 ins_long(PyObject *d, char *name, long val)
3628 {
3629 PyObject *v = PyInt_FromLong(val);
3630 if (v) {
3631 PyDict_SetItemString(d, name, v);
3632 Py_DECREF(v);
3633 }
3634 }
3635 static void
ins_string(PyObject * d,char * name,char * val)3636 ins_string(PyObject *d, char *name, char *val)
3637 {
3638 PyObject *v = PyString_FromString(val);
3639 if (v) {
3640 PyDict_SetItemString(d, name, v);
3641 Py_DECREF(v);
3642 }
3643 }
3644
3645
3646 PyMODINIT_FUNC
init_tkinter(void)3647 init_tkinter(void)
3648 {
3649 PyObject *m, *d;
3650
3651 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3652
3653 #ifdef WITH_THREAD
3654 tcl_lock = PyThread_allocate_lock();
3655 #endif
3656
3657 m = Py_InitModule("_tkinter", moduleMethods);
3658 if (m == NULL)
3659 return;
3660
3661 d = PyModule_GetDict(m);
3662 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3663 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3664
3665 ins_long(d, "READABLE", TCL_READABLE);
3666 ins_long(d, "WRITABLE", TCL_WRITABLE);
3667 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3668 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3669 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3670 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3671 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3672 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3673 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3674 ins_string(d, "TK_VERSION", TK_VERSION);
3675 ins_string(d, "TCL_VERSION", TCL_VERSION);
3676
3677 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3678
3679 Py_TYPE(&Tktt_Type) = &PyType_Type;
3680 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3681
3682 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3683 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3684
3685 #ifdef TK_AQUA
3686 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3687 * start waking up. Note that Tcl_FindExecutable will do this, this
3688 * code must be above it! The original warning from
3689 * tkMacOSXAppInit.c is copied below.
3690 *
3691 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3692 * Tcl interpreter for now. It probably should work to do this
3693 * in the other order, but for now it doesn't seem to.
3694 *
3695 */
3696 Tk_MacOSXSetupTkNotifier();
3697 #endif
3698
3699
3700 /* This helps the dynamic loader; in Unicode aware Tcl versions
3701 it also helps Tcl find its encodings. */
3702 Tcl_FindExecutable(Py_GetProgramName());
3703
3704 if (PyErr_Occurred())
3705 return;
3706
3707 #if 0
3708 /* This was not a good idea; through <Destroy> bindings,
3709 Tcl_Finalize() may invoke Python code but at that point the
3710 interpreter and thread state have already been destroyed! */
3711 Py_AtExit(Tcl_Finalize);
3712 #endif
3713
3714 }
3715