source: python/trunk/Modules/_tkinter.c@ 399

Last change on this file since 399 was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

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