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