source: vendor/python/2.5/Modules/_tkinter.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

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