source: python/vendor/Python-2.6.5/Modules/_tkinter.c

Last change on this file was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 71.0 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) (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
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
499static PyObject *
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 = NULL;
949 Py_ssize_t i;
950 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
951 if (allocsize >= size)
952 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
953 /* Else overflow occurred, and we take the next exit */
954 if (!outbuf) {
955 PyErr_NoMemory();
956 return NULL;
957 }
958 for (i = 0; i < size; i++) {
959 if (inbuf[i] >= 0x10000) {
960 /* Tcl doesn't do UTF-16, yet. */
961 PyErr_SetString(PyExc_ValueError,
962 "unsupported character");
963 ckfree(FREECAST outbuf);
964 return NULL;
965 }
966 outbuf[i] = inbuf[i];
967 }
968 result = Tcl_NewUnicodeObj(outbuf, size);
969 ckfree(FREECAST outbuf);
970 return result;
971#else
972 return Tcl_NewUnicodeObj(inbuf, size);
973#endif
974
975 }
976#endif
977 else if(PyTclObject_Check(value)) {
978 Tcl_Obj *v = ((PyTclObject*)value)->value;
979 Tcl_IncrRefCount(v);
980 return v;
981 }
982 else {
983 PyObject *v = PyObject_Str(value);
984 if (!v)
985 return 0;
986 result = AsObj(v);
987 Py_DECREF(v);
988 return result;
989 }
990}
991
992static PyObject*
993FromObj(PyObject* tkapp, Tcl_Obj *value)
994{
995 PyObject *result = NULL;
996 TkappObject *app = (TkappObject*)tkapp;
997
998 if (value->typePtr == NULL) {
999 /* If the result contains any bytes with the top bit set,
1000 it's UTF-8 and we should decode it to Unicode */
1001#ifdef Py_USING_UNICODE
1002 int i;
1003 char *s = value->bytes;
1004 int len = value->length;
1005 for (i = 0; i < len; i++) {
1006 if (value->bytes[i] & 0x80)
1007 break;
1008 }
1009
1010 if (i == value->length)
1011 result = PyString_FromStringAndSize(s, len);
1012 else {
1013 /* Convert UTF-8 to Unicode string */
1014 result = PyUnicode_DecodeUTF8(s, len, "strict");
1015 if (result == NULL) {
1016 PyErr_Clear();
1017 result = PyString_FromStringAndSize(s, len);
1018 }
1019 }
1020#else
1021 result = PyString_FromStringAndSize(value->bytes, value->length);
1022#endif
1023 return result;
1024 }
1025
1026 if (value->typePtr == app->BooleanType) {
1027 result = value->internalRep.longValue ? Py_True : Py_False;
1028 Py_INCREF(result);
1029 return result;
1030 }
1031
1032 if (value->typePtr == app->ByteArrayType) {
1033 int size;
1034 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1035 return PyString_FromStringAndSize(data, size);
1036 }
1037
1038 if (value->typePtr == app->DoubleType) {
1039 return PyFloat_FromDouble(value->internalRep.doubleValue);
1040 }
1041
1042 if (value->typePtr == app->IntType) {
1043 return PyInt_FromLong(value->internalRep.longValue);
1044 }
1045
1046 if (value->typePtr == app->ListType) {
1047 int size;
1048 int i, status;
1049 PyObject *elem;
1050 Tcl_Obj *tcl_elem;
1051
1052 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1053 if (status == TCL_ERROR)
1054 return Tkinter_Error(tkapp);
1055 result = PyTuple_New(size);
1056 if (!result)
1057 return NULL;
1058 for (i = 0; i < size; i++) {
1059 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1060 value, i, &tcl_elem);
1061 if (status == TCL_ERROR) {
1062 Py_DECREF(result);
1063 return Tkinter_Error(tkapp);
1064 }
1065 elem = FromObj(tkapp, tcl_elem);
1066 if (!elem) {
1067 Py_DECREF(result);
1068 return NULL;
1069 }
1070 PyTuple_SetItem(result, i, elem);
1071 }
1072 return result;
1073 }
1074
1075 if (value->typePtr == app->ProcBodyType) {
1076 /* fall through: return tcl object. */
1077 }
1078
1079 if (value->typePtr == app->StringType) {
1080#ifdef Py_USING_UNICODE
1081#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1082 PyObject *result;
1083 int size;
1084 Tcl_UniChar *input;
1085 Py_UNICODE *output;
1086
1087 size = Tcl_GetCharLength(value);
1088 result = PyUnicode_FromUnicode(NULL, size);
1089 if (!result)
1090 return NULL;
1091 input = Tcl_GetUnicode(value);
1092 output = PyUnicode_AS_UNICODE(result);
1093 while (size--)
1094 *output++ = *input++;
1095 return result;
1096#else
1097 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1098 Tcl_GetCharLength(value));
1099#endif
1100#else
1101 int size;
1102 char *c;
1103 c = Tcl_GetStringFromObj(value, &size);
1104 return PyString_FromStringAndSize(c, size);
1105#endif
1106 }
1107
1108 return newPyTclObject(value);
1109}
1110
1111/* This mutex synchronizes inter-thread command calls. */
1112
1113TCL_DECLARE_MUTEX(call_mutex)
1114
1115typedef struct Tkapp_CallEvent {
1116 Tcl_Event ev; /* Must be first */
1117 TkappObject *self;
1118 PyObject *args;
1119 int flags;
1120 PyObject **res;
1121 PyObject **exc_type, **exc_value, **exc_tb;
1122 Tcl_Condition done;
1123} Tkapp_CallEvent;
1124
1125void
1126Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1127{
1128 int i;
1129 for (i = 0; i < objc; i++)
1130 Tcl_DecrRefCount(objv[i]);
1131 if (objv != objStore)
1132 ckfree(FREECAST objv);
1133}
1134
1135/* Convert Python objects to Tcl objects. This must happen in the
1136 interpreter thread, which may or may not be the calling thread. */
1137
1138static Tcl_Obj**
1139Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1140{
1141 Tcl_Obj **objv = objStore;
1142 int objc = 0, i;
1143 if (args == NULL)
1144 /* do nothing */;
1145
1146 else if (!PyTuple_Check(args)) {
1147 objv[0] = AsObj(args);
1148 if (objv[0] == 0)
1149 goto finally;
1150 objc = 1;
1151 Tcl_IncrRefCount(objv[0]);
1152 }
1153 else {
1154 objc = PyTuple_Size(args);
1155
1156 if (objc > ARGSZ) {
1157 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1158 if (objv == NULL) {
1159 PyErr_NoMemory();
1160 objc = 0;
1161 goto finally;
1162 }
1163 }
1164
1165 for (i = 0; i < objc; i++) {
1166 PyObject *v = PyTuple_GetItem(args, i);
1167 if (v == Py_None) {
1168 objc = i;
1169 break;
1170 }
1171 objv[i] = AsObj(v);
1172 if (!objv[i]) {
1173 /* Reset objc, so it attempts to clear
1174 objects only up to i. */
1175 objc = i;
1176 goto finally;
1177 }
1178 Tcl_IncrRefCount(objv[i]);
1179 }
1180 }
1181 *pobjc = objc;
1182 return objv;
1183finally:
1184 Tkapp_CallDeallocArgs(objv, objStore, objc);
1185 return NULL;
1186}
1187
1188/* Convert the results of a command call into a Python objects. */
1189
1190static PyObject*
1191Tkapp_CallResult(TkappObject *self)
1192{
1193 PyObject *res = NULL;
1194 if(self->wantobjects) {
1195 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1196 /* Not sure whether the IncrRef is necessary, but something
1197 may overwrite the interpreter result while we are
1198 converting it. */
1199 Tcl_IncrRefCount(value);
1200 res = FromObj((PyObject*)self, value);
1201 Tcl_DecrRefCount(value);
1202 } else {
1203 const char *s = Tcl_GetStringResult(self->interp);
1204 const char *p = s;
1205
1206 /* If the result contains any bytes with the top bit set,
1207 it's UTF-8 and we should decode it to Unicode */
1208#ifdef Py_USING_UNICODE
1209 while (*p != '\0') {
1210 if (*p & 0x80)
1211 break;
1212 p++;
1213 }
1214
1215 if (*p == '\0')
1216 res = PyString_FromStringAndSize(s, (int)(p-s));
1217 else {
1218 /* Convert UTF-8 to Unicode string */
1219 p = strchr(p, '\0');
1220 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1221 if (res == NULL) {
1222 PyErr_Clear();
1223 res = PyString_FromStringAndSize(s, (int)(p-s));
1224 }
1225 }
1226#else
1227 p = strchr(p, '\0');
1228 res = PyString_FromStringAndSize(s, (int)(p-s));
1229#endif
1230 }
1231 return res;
1232}
1233
1234/* Tkapp_CallProc is the event procedure that is executed in the context of
1235 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1236 hold the Python lock. */
1237
1238static int
1239Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1240{
1241 Tcl_Obj *objStore[ARGSZ];
1242 Tcl_Obj **objv;
1243 int objc;
1244 int i;
1245 ENTER_PYTHON
1246 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1247 if (!objv) {
1248 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1249 *(e->res) = NULL;
1250 }
1251 LEAVE_PYTHON
1252 if (!objv)
1253 goto done;
1254 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1255 ENTER_PYTHON
1256 if (i == TCL_ERROR) {
1257 *(e->res) = NULL;
1258 *(e->exc_type) = NULL;
1259 *(e->exc_tb) = NULL;
1260 *(e->exc_value) = PyObject_CallFunction(
1261 Tkinter_TclError, "s",
1262 Tcl_GetStringResult(e->self->interp));
1263 }
1264 else {
1265 *(e->res) = Tkapp_CallResult(e->self);
1266 }
1267 LEAVE_PYTHON
1268
1269 Tkapp_CallDeallocArgs(objv, objStore, objc);
1270done:
1271 /* Wake up calling thread. */
1272 Tcl_MutexLock(&call_mutex);
1273 Tcl_ConditionNotify(&e->done);
1274 Tcl_MutexUnlock(&call_mutex);
1275 return 1;
1276}
1277
1278/* This is the main entry point for calling a Tcl command.
1279 It supports three cases, with regard to threading:
1280 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1281 the context of the calling thread.
1282 2. Tcl is threaded, caller of the command is in the interpreter thread:
1283 Execute the command in the calling thread. Since the Tcl lock will
1284 not be used, we can merge that with case 1.
1285 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1286 the interpreter thread. Allocation of Tcl objects needs to occur in the
1287 interpreter thread, so we ship the PyObject* args to the target thread,
1288 and perform processing there. */
1289
1290static PyObject *
1291Tkapp_Call(PyObject *selfptr, PyObject *args)
1292{
1293 Tcl_Obj *objStore[ARGSZ];
1294 Tcl_Obj **objv = NULL;
1295 int objc, i;
1296 PyObject *res = NULL;
1297 TkappObject *self = (TkappObject*)selfptr;
1298 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1299
1300 /* If args is a single tuple, replace with contents of tuple */
1301 if (1 == PyTuple_Size(args)){
1302 PyObject* item = PyTuple_GetItem(args, 0);
1303 if (PyTuple_Check(item))
1304 args = item;
1305 }
1306#ifdef WITH_THREAD
1307 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1308 /* We cannot call the command directly. Instead, we must
1309 marshal the parameters to the interpreter thread. */
1310 Tkapp_CallEvent *ev;
1311 PyObject *exc_type, *exc_value, *exc_tb;
1312 if (!WaitForMainloop(self))
1313 return NULL;
1314 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1315 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1316 ev->self = self;
1317 ev->args = args;
1318 ev->res = &res;
1319 ev->exc_type = &exc_type;
1320 ev->exc_value = &exc_value;
1321 ev->exc_tb = &exc_tb;
1322 ev->done = (Tcl_Condition)0;
1323
1324 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1325
1326 if (res == NULL) {
1327 if (exc_type)
1328 PyErr_Restore(exc_type, exc_value, exc_tb);
1329 else
1330 PyErr_SetObject(Tkinter_TclError, exc_value);
1331 }
1332 }
1333 else
1334#endif
1335 {
1336
1337 objv = Tkapp_CallArgs(args, objStore, &objc);
1338 if (!objv)
1339 return NULL;
1340
1341 ENTER_TCL
1342
1343 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1344
1345 ENTER_OVERLAP
1346
1347 if (i == TCL_ERROR)
1348 Tkinter_Error(selfptr);
1349 else
1350 res = Tkapp_CallResult(self);
1351
1352 LEAVE_OVERLAP_TCL
1353
1354 Tkapp_CallDeallocArgs(objv, objStore, objc);
1355 }
1356 return res;
1357}
1358
1359
1360static PyObject *
1361Tkapp_GlobalCall(PyObject *self, PyObject *args)
1362{
1363 /* Could do the same here as for Tkapp_Call(), but this is not used
1364 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1365 way for the user to do what all its Global* variants do (save and
1366 reset the scope pointer, call the local version, restore the saved
1367 scope pointer). */
1368
1369 char *cmd;
1370 PyObject *res = NULL;
1371
1372 CHECK_TCL_APPARTMENT;
1373
1374 cmd = Merge(args);
1375 if (cmd) {
1376 int err;
1377 ENTER_TCL
1378 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1379 ENTER_OVERLAP
1380 if (err == TCL_ERROR)
1381 res = Tkinter_Error(self);
1382 else
1383 res = PyString_FromString(Tkapp_Result(self));
1384 LEAVE_OVERLAP_TCL
1385 ckfree(cmd);
1386 }
1387
1388 return res;
1389}
1390
1391static PyObject *
1392Tkapp_Eval(PyObject *self, PyObject *args)
1393{
1394 char *script;
1395 PyObject *res = NULL;
1396 int err;
1397
1398 if (!PyArg_ParseTuple(args, "s:eval", &script))
1399 return NULL;
1400
1401 CHECK_TCL_APPARTMENT;
1402
1403 ENTER_TCL
1404 err = Tcl_Eval(Tkapp_Interp(self), script);
1405 ENTER_OVERLAP
1406 if (err == TCL_ERROR)
1407 res = Tkinter_Error(self);
1408 else
1409 res = PyString_FromString(Tkapp_Result(self));
1410 LEAVE_OVERLAP_TCL
1411 return res;
1412}
1413
1414static PyObject *
1415Tkapp_GlobalEval(PyObject *self, PyObject *args)
1416{
1417 char *script;
1418 PyObject *res = NULL;
1419 int err;
1420
1421 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1422 return NULL;
1423
1424 CHECK_TCL_APPARTMENT;
1425
1426 ENTER_TCL
1427 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1428 ENTER_OVERLAP
1429 if (err == TCL_ERROR)
1430 res = Tkinter_Error(self);
1431 else
1432 res = PyString_FromString(Tkapp_Result(self));
1433 LEAVE_OVERLAP_TCL
1434 return res;
1435}
1436
1437static PyObject *
1438Tkapp_EvalFile(PyObject *self, PyObject *args)
1439{
1440 char *fileName;
1441 PyObject *res = NULL;
1442 int err;
1443
1444 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1445 return NULL;
1446
1447 CHECK_TCL_APPARTMENT;
1448
1449 ENTER_TCL
1450 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1451 ENTER_OVERLAP
1452 if (err == TCL_ERROR)
1453 res = Tkinter_Error(self);
1454
1455 else
1456 res = PyString_FromString(Tkapp_Result(self));
1457 LEAVE_OVERLAP_TCL
1458 return res;
1459}
1460
1461static PyObject *
1462Tkapp_Record(PyObject *self, PyObject *args)
1463{
1464 char *script;
1465 PyObject *res = NULL;
1466 int err;
1467
1468 if (!PyArg_ParseTuple(args, "s", &script))
1469 return NULL;
1470
1471 CHECK_TCL_APPARTMENT;
1472
1473 ENTER_TCL
1474 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1475 ENTER_OVERLAP
1476 if (err == TCL_ERROR)
1477 res = Tkinter_Error(self);
1478 else
1479 res = PyString_FromString(Tkapp_Result(self));
1480 LEAVE_OVERLAP_TCL
1481 return res;
1482}
1483
1484static PyObject *
1485Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1486{
1487 char *msg;
1488
1489 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1490 return NULL;
1491 CHECK_TCL_APPARTMENT;
1492
1493 ENTER_TCL
1494 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1495 LEAVE_TCL
1496
1497 Py_INCREF(Py_None);
1498 return Py_None;
1499}
1500
1501
1502
1503
1504/** Tcl Variable **/
1505
1506TCL_DECLARE_MUTEX(var_mutex)
1507
1508typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1509typedef struct VarEvent {
1510 Tcl_Event ev; /* must be first */
1511 PyObject *self;
1512 PyObject *args;
1513 int flags;
1514 EventFunc func;
1515 PyObject **res;
1516 PyObject **exc_type;
1517 PyObject **exc_val;
1518 Tcl_Condition cond;
1519} VarEvent;
1520
1521static int
1522varname_converter(PyObject *in, void *_out)
1523{
1524 char **out = (char**)_out;
1525 if (PyString_Check(in)) {
1526 *out = PyString_AsString(in);
1527 return 1;
1528 }
1529 if (PyTclObject_Check(in)) {
1530 *out = PyTclObject_TclString(in);
1531 return 1;
1532 }
1533 /* XXX: Should give diagnostics. */
1534 return 0;
1535}
1536
1537static void
1538var_perform(VarEvent *ev)
1539{
1540 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1541 if (!*(ev->res)) {
1542 PyObject *exc, *val, *tb;
1543 PyErr_Fetch(&exc, &val, &tb);
1544 PyErr_NormalizeException(&exc, &val, &tb);
1545 *(ev->exc_type) = exc;
1546 *(ev->exc_val) = val;
1547 Py_DECREF(tb);
1548 }
1549
1550}
1551
1552static int
1553var_proc(VarEvent* ev, int flags)
1554{
1555 ENTER_PYTHON
1556 var_perform(ev);
1557 Tcl_MutexLock(&var_mutex);
1558 Tcl_ConditionNotify(&ev->cond);
1559 Tcl_MutexUnlock(&var_mutex);
1560 LEAVE_PYTHON
1561 return 1;
1562}
1563
1564static PyObject*
1565var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1566{
1567 TkappObject *self = (TkappObject*)selfptr;
1568#ifdef WITH_THREAD
1569 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1570 TkappObject *self = (TkappObject*)selfptr;
1571 VarEvent *ev;
1572 PyObject *res, *exc_type, *exc_val;
1573
1574 /* The current thread is not the interpreter thread. Marshal
1575 the call to the interpreter thread, then wait for
1576 completion. */
1577 if (!WaitForMainloop(self))
1578 return NULL;
1579
1580 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1581
1582 ev->self = selfptr;
1583 ev->args = args;
1584 ev->flags = flags;
1585 ev->func = func;
1586 ev->res = &res;
1587 ev->exc_type = &exc_type;
1588 ev->exc_val = &exc_val;
1589 ev->cond = NULL;
1590 ev->ev.proc = (Tcl_EventProc*)var_proc;
1591 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1592 if (!res) {
1593 PyErr_SetObject(exc_type, exc_val);
1594 Py_DECREF(exc_type);
1595 Py_DECREF(exc_val);
1596 return NULL;
1597 }
1598 return res;
1599 }
1600#endif
1601 /* Tcl is not threaded, or this is the interpreter thread. */
1602 return func(selfptr, args, flags);
1603}
1604
1605static PyObject *
1606SetVar(PyObject *self, PyObject *args, int flags)
1607{
1608 char *name1, *name2;
1609 PyObject *newValue;
1610 PyObject *res = NULL;
1611 Tcl_Obj *newval, *ok;
1612
1613 if (PyArg_ParseTuple(args, "O&O:setvar",
1614 varname_converter, &name1, &newValue)) {
1615 /* XXX Acquire tcl lock??? */
1616 newval = AsObj(newValue);
1617 if (newval == NULL)
1618 return NULL;
1619 ENTER_TCL
1620 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1621 newval, flags);
1622 ENTER_OVERLAP
1623 if (!ok)
1624 Tkinter_Error(self);
1625 else {
1626 res = Py_None;
1627 Py_INCREF(res);
1628 }
1629 LEAVE_OVERLAP_TCL
1630 }
1631 else {
1632 PyErr_Clear();
1633 if (PyArg_ParseTuple(args, "ssO:setvar",
1634 &name1, &name2, &newValue)) {
1635 /* XXX must hold tcl lock already??? */
1636 newval = AsObj(newValue);
1637 ENTER_TCL
1638 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1639 ENTER_OVERLAP
1640 if (!ok)
1641 Tkinter_Error(self);
1642 else {
1643 res = Py_None;
1644 Py_INCREF(res);
1645 }
1646 LEAVE_OVERLAP_TCL
1647 }
1648 else {
1649 return NULL;
1650 }
1651 }
1652 return res;
1653}
1654
1655static PyObject *
1656Tkapp_SetVar(PyObject *self, PyObject *args)
1657{
1658 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1659}
1660
1661static PyObject *
1662Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1663{
1664 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1665}
1666
1667
1668
1669
1670static PyObject *
1671GetVar(PyObject *self, PyObject *args, int flags)
1672{
1673 char *name1, *name2=NULL;
1674 PyObject *res = NULL;
1675 Tcl_Obj *tres;
1676
1677 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1678 varname_converter, &name1, &name2))
1679 return NULL;
1680
1681 ENTER_TCL
1682 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1683 ENTER_OVERLAP
1684 if (tres == NULL) {
1685 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1686 } else {
1687 if (((TkappObject*)self)->wantobjects) {
1688 res = FromObj(self, tres);
1689 }
1690 else {
1691 res = PyString_FromString(Tcl_GetString(tres));
1692 }
1693 }
1694 LEAVE_OVERLAP_TCL
1695 return res;
1696}
1697
1698static PyObject *
1699Tkapp_GetVar(PyObject *self, PyObject *args)
1700{
1701 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1702}
1703
1704static PyObject *
1705Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1706{
1707 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1708}
1709
1710
1711
1712
1713static PyObject *
1714UnsetVar(PyObject *self, PyObject *args, int flags)
1715{
1716 char *name1, *name2=NULL;
1717 int code;
1718 PyObject *res = NULL;
1719
1720 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1721 return NULL;
1722
1723 ENTER_TCL
1724 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1725 ENTER_OVERLAP
1726 if (code == TCL_ERROR)
1727 res = Tkinter_Error(self);
1728 else {
1729 Py_INCREF(Py_None);
1730 res = Py_None;
1731 }
1732 LEAVE_OVERLAP_TCL
1733 return res;
1734}
1735
1736static PyObject *
1737Tkapp_UnsetVar(PyObject *self, PyObject *args)
1738{
1739 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1740}
1741
1742static PyObject *
1743Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1744{
1745 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1746}
1747
1748
1749
1750
1751/** Tcl to Python **/
1752
1753static PyObject *
1754Tkapp_GetInt(PyObject *self, PyObject *args)
1755{
1756 char *s;
1757 int v;
1758
1759 if (PyTuple_Size(args) == 1) {
1760 PyObject* o = PyTuple_GetItem(args, 0);
1761 if (PyInt_Check(o)) {
1762 Py_INCREF(o);
1763 return o;
1764 }
1765 }
1766 if (!PyArg_ParseTuple(args, "s:getint", &s))
1767 return NULL;
1768 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1769 return Tkinter_Error(self);
1770 return Py_BuildValue("i", v);
1771}
1772
1773static PyObject *
1774Tkapp_GetDouble(PyObject *self, PyObject *args)
1775{
1776 char *s;
1777 double v;
1778
1779 if (PyTuple_Size(args) == 1) {
1780 PyObject *o = PyTuple_GetItem(args, 0);
1781 if (PyFloat_Check(o)) {
1782 Py_INCREF(o);
1783 return o;
1784 }
1785 }
1786 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1787 return NULL;
1788 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1789 return Tkinter_Error(self);
1790 return Py_BuildValue("d", v);
1791}
1792
1793static PyObject *
1794Tkapp_GetBoolean(PyObject *self, PyObject *args)
1795{
1796 char *s;
1797 int v;
1798
1799 if (PyTuple_Size(args) == 1) {
1800 PyObject *o = PyTuple_GetItem(args, 0);
1801 if (PyInt_Check(o)) {
1802 Py_INCREF(o);
1803 return o;
1804 }
1805 }
1806 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1807 return NULL;
1808 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1809 return Tkinter_Error(self);
1810 return PyBool_FromLong(v);
1811}
1812
1813static PyObject *
1814Tkapp_ExprString(PyObject *self, PyObject *args)
1815{
1816 char *s;
1817 PyObject *res = NULL;
1818 int retval;
1819
1820 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1821 return NULL;
1822
1823 CHECK_TCL_APPARTMENT;
1824
1825 ENTER_TCL
1826 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1827 ENTER_OVERLAP
1828 if (retval == TCL_ERROR)
1829 res = Tkinter_Error(self);
1830 else
1831 res = Py_BuildValue("s", Tkapp_Result(self));
1832 LEAVE_OVERLAP_TCL
1833 return res;
1834}
1835
1836static PyObject *
1837Tkapp_ExprLong(PyObject *self, PyObject *args)
1838{
1839 char *s;
1840 PyObject *res = NULL;
1841 int retval;
1842 long v;
1843
1844 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1845 return NULL;
1846
1847 CHECK_TCL_APPARTMENT;
1848
1849 ENTER_TCL
1850 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1851 ENTER_OVERLAP
1852 if (retval == TCL_ERROR)
1853 res = Tkinter_Error(self);
1854 else
1855 res = Py_BuildValue("l", v);
1856 LEAVE_OVERLAP_TCL
1857 return res;
1858}
1859
1860static PyObject *
1861Tkapp_ExprDouble(PyObject *self, PyObject *args)
1862{
1863 char *s;
1864 PyObject *res = NULL;
1865 double v;
1866 int retval;
1867
1868 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1869 return NULL;
1870 CHECK_TCL_APPARTMENT;
1871 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1872 ENTER_TCL
1873 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1874 ENTER_OVERLAP
1875 PyFPE_END_PROTECT(retval)
1876 if (retval == TCL_ERROR)
1877 res = Tkinter_Error(self);
1878 else
1879 res = Py_BuildValue("d", v);
1880 LEAVE_OVERLAP_TCL
1881 return res;
1882}
1883
1884static PyObject *
1885Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1886{
1887 char *s;
1888 PyObject *res = NULL;
1889 int retval;
1890 int v;
1891
1892 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1893 return NULL;
1894 CHECK_TCL_APPARTMENT;
1895 ENTER_TCL
1896 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1897 ENTER_OVERLAP
1898 if (retval == TCL_ERROR)
1899 res = Tkinter_Error(self);
1900 else
1901 res = Py_BuildValue("i", v);
1902 LEAVE_OVERLAP_TCL
1903 return res;
1904}
1905
1906
1907
1908
1909static PyObject *
1910Tkapp_SplitList(PyObject *self, PyObject *args)
1911{
1912 char *list;
1913 int argc;
1914 char **argv;
1915 PyObject *v;
1916 int i;
1917
1918 if (PyTuple_Size(args) == 1) {
1919 v = PyTuple_GetItem(args, 0);
1920 if (PyTuple_Check(v)) {
1921 Py_INCREF(v);
1922 return v;
1923 }
1924 }
1925 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1926 return NULL;
1927
1928 if (Tcl_SplitList(Tkapp_Interp(self), list,
1929 &argc, &argv) == TCL_ERROR) {
1930 PyMem_Free(list);
1931 return Tkinter_Error(self);
1932 }
1933
1934 if (!(v = PyTuple_New(argc)))
1935 goto finally;
1936
1937 for (i = 0; i < argc; i++) {
1938 PyObject *s = PyString_FromString(argv[i]);
1939 if (!s || PyTuple_SetItem(v, i, s)) {
1940 Py_DECREF(v);
1941 v = NULL;
1942 goto finally;
1943 }
1944 }
1945
1946 finally:
1947 ckfree(FREECAST argv);
1948 PyMem_Free(list);
1949 return v;
1950}
1951
1952static PyObject *
1953Tkapp_Split(PyObject *self, PyObject *args)
1954{
1955 PyObject *v;
1956 char *list;
1957
1958 if (PyTuple_Size(args) == 1) {
1959 PyObject* o = PyTuple_GetItem(args, 0);
1960 if (PyTuple_Check(o)) {
1961 o = SplitObj(o);
1962 return o;
1963 }
1964 }
1965 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1966 return NULL;
1967 v = Split(list);
1968 PyMem_Free(list);
1969 return v;
1970}
1971
1972static PyObject *
1973Tkapp_Merge(PyObject *self, PyObject *args)
1974{
1975 char *s = Merge(args);
1976 PyObject *res = NULL;
1977
1978 if (s) {
1979 res = PyString_FromString(s);
1980 ckfree(s);
1981 }
1982
1983 return res;
1984}
1985
1986
1987
1988
1989/** Tcl Command **/
1990
1991/* Client data struct */
1992typedef struct {
1993 PyObject *self;
1994 PyObject *func;
1995} PythonCmd_ClientData;
1996
1997static int
1998PythonCmd_Error(Tcl_Interp *interp)
1999{
2000 errorInCmd = 1;
2001 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2002 LEAVE_PYTHON
2003 return TCL_ERROR;
2004}
2005
2006/* This is the Tcl command that acts as a wrapper for Python
2007 * function or method.
2008 */
2009static int
2010PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2011{
2012 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2013 PyObject *self, *func, *arg, *res;
2014 int i, rv;
2015 Tcl_Obj *obj_res;
2016
2017 ENTER_PYTHON
2018
2019 /* TBD: no error checking here since we know, via the
2020 * Tkapp_CreateCommand() that the client data is a two-tuple
2021 */
2022 self = data->self;
2023 func = data->func;
2024
2025 /* Create argument list (argv1, ..., argvN) */
2026 if (!(arg = PyTuple_New(argc - 1)))
2027 return PythonCmd_Error(interp);
2028
2029 for (i = 0; i < (argc - 1); i++) {
2030 PyObject *s = PyString_FromString(argv[i + 1]);
2031 if (!s || PyTuple_SetItem(arg, i, s)) {
2032 Py_DECREF(arg);
2033 return PythonCmd_Error(interp);
2034 }
2035 }
2036 res = PyEval_CallObject(func, arg);
2037 Py_DECREF(arg);
2038
2039 if (res == NULL)
2040 return PythonCmd_Error(interp);
2041
2042 obj_res = AsObj(res);
2043 if (obj_res == NULL) {
2044 Py_DECREF(res);
2045 return PythonCmd_Error(interp);
2046 }
2047 else {
2048 Tcl_SetObjResult(interp, obj_res);
2049 rv = TCL_OK;
2050 }
2051
2052 Py_DECREF(res);
2053
2054 LEAVE_PYTHON
2055
2056 return rv;
2057}
2058
2059static void
2060PythonCmdDelete(ClientData clientData)
2061{
2062 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2063
2064 ENTER_PYTHON
2065 Py_XDECREF(data->self);
2066 Py_XDECREF(data->func);
2067 PyMem_DEL(data);
2068 LEAVE_PYTHON
2069}
2070
2071
2072
2073
2074
2075TCL_DECLARE_MUTEX(command_mutex)
2076
2077typedef struct CommandEvent{
2078 Tcl_Event ev;
2079 Tcl_Interp* interp;
2080 char *name;
2081 int create;
2082 int *status;
2083 ClientData *data;
2084 Tcl_Condition done;
2085} CommandEvent;
2086
2087static int
2088Tkapp_CommandProc(CommandEvent *ev, int flags)
2089{
2090 if (ev->create)
2091 *ev->status = Tcl_CreateCommand(
2092 ev->interp, ev->name, PythonCmd,
2093 ev->data, PythonCmdDelete) == NULL;
2094 else
2095 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2096 Tcl_MutexLock(&command_mutex);
2097 Tcl_ConditionNotify(&ev->done);
2098 Tcl_MutexUnlock(&command_mutex);
2099 return 1;
2100}
2101
2102static PyObject *
2103Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2104{
2105 TkappObject *self = (TkappObject*)selfptr;
2106 PythonCmd_ClientData *data;
2107 char *cmdName;
2108 PyObject *func;
2109 int err;
2110
2111 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2112 return NULL;
2113 if (!PyCallable_Check(func)) {
2114 PyErr_SetString(PyExc_TypeError, "command not callable");
2115 return NULL;
2116 }
2117
2118#ifdef WITH_THREAD
2119 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2120 !WaitForMainloop(self))
2121 return NULL;
2122#endif
2123
2124 data = PyMem_NEW(PythonCmd_ClientData, 1);
2125 if (!data)
2126 return PyErr_NoMemory();
2127 Py_INCREF(self);
2128 Py_INCREF(func);
2129 data->self = selfptr;
2130 data->func = func;
2131
2132 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2133 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2134 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2135 ev->interp = self->interp;
2136 ev->create = 1;
2137 ev->name = cmdName;
2138 ev->data = (ClientData)data;
2139 ev->status = &err;
2140 ev->done = NULL;
2141 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2142 }
2143 else {
2144 ENTER_TCL
2145 err = Tcl_CreateCommand(
2146 Tkapp_Interp(self), cmdName, PythonCmd,
2147 (ClientData)data, PythonCmdDelete) == NULL;
2148 LEAVE_TCL
2149 }
2150 if (err) {
2151 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2152 PyMem_DEL(data);
2153 return NULL;
2154 }
2155
2156 Py_INCREF(Py_None);
2157 return Py_None;
2158}
2159
2160
2161
2162
2163static PyObject *
2164Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2165{
2166 TkappObject *self = (TkappObject*)selfptr;
2167 char *cmdName;
2168 int err;
2169
2170 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2171 return NULL;
2172 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2173 CommandEvent *ev;
2174 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2175 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2176 ev->interp = self->interp;
2177 ev->create = 0;
2178 ev->name = cmdName;
2179 ev->status = &err;
2180 ev->done = NULL;
2181 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2182 &command_mutex);
2183 }
2184 else {
2185 ENTER_TCL
2186 err = Tcl_DeleteCommand(self->interp, cmdName);
2187 LEAVE_TCL
2188 }
2189 if (err == -1) {
2190 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2191 return NULL;
2192 }
2193 Py_INCREF(Py_None);
2194 return Py_None;
2195}
2196
2197
2198
2199
2200#ifdef HAVE_CREATEFILEHANDLER
2201/** File Handler **/
2202
2203typedef struct _fhcdata {
2204 PyObject *func;
2205 PyObject *file;
2206 int id;
2207 struct _fhcdata *next;
2208} FileHandler_ClientData;
2209
2210static FileHandler_ClientData *HeadFHCD;
2211
2212static FileHandler_ClientData *
2213NewFHCD(PyObject *func, PyObject *file, int id)
2214{
2215 FileHandler_ClientData *p;
2216 p = PyMem_NEW(FileHandler_ClientData, 1);
2217 if (p != NULL) {
2218 Py_XINCREF(func);
2219 Py_XINCREF(file);
2220 p->func = func;
2221 p->file = file;
2222 p->id = id;
2223 p->next = HeadFHCD;
2224 HeadFHCD = p;
2225 }
2226 return p;
2227}
2228
2229static void
2230DeleteFHCD(int id)
2231{
2232 FileHandler_ClientData *p, **pp;
2233
2234 pp = &HeadFHCD;
2235 while ((p = *pp) != NULL) {
2236 if (p->id == id) {
2237 *pp = p->next;
2238 Py_XDECREF(p->func);
2239 Py_XDECREF(p->file);
2240 PyMem_DEL(p);
2241 }
2242 else
2243 pp = &p->next;
2244 }
2245}
2246
2247static void
2248FileHandler(ClientData clientData, int mask)
2249{
2250 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2251 PyObject *func, *file, *arg, *res;
2252
2253 ENTER_PYTHON
2254 func = data->func;
2255 file = data->file;
2256
2257 arg = Py_BuildValue("(Oi)", file, (long) mask);
2258 res = PyEval_CallObject(func, arg);
2259 Py_DECREF(arg);
2260
2261 if (res == NULL) {
2262 errorInCmd = 1;
2263 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2264 }
2265 Py_XDECREF(res);
2266 LEAVE_PYTHON
2267}
2268
2269static PyObject *
2270Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2271 /* args is (file, mask, func) */
2272{
2273 FileHandler_ClientData *data;
2274 PyObject *file, *func;
2275 int mask, tfile;
2276
2277 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2278 &file, &mask, &func))
2279 return NULL;
2280
2281#ifdef WITH_THREAD
2282 if (!self && !tcl_lock) {
2283 /* We don't have the Tcl lock since Tcl is threaded. */
2284 PyErr_SetString(PyExc_RuntimeError,
2285 "_tkinter.createfilehandler not supported "
2286 "for threaded Tcl");
2287 return NULL;
2288 }
2289#endif
2290
2291 if (self) {
2292 CHECK_TCL_APPARTMENT;
2293 }
2294
2295 tfile = PyObject_AsFileDescriptor(file);
2296 if (tfile < 0)
2297 return NULL;
2298 if (!PyCallable_Check(func)) {
2299 PyErr_SetString(PyExc_TypeError, "bad argument list");
2300 return NULL;
2301 }
2302
2303 data = NewFHCD(func, file, tfile);
2304 if (data == NULL)
2305 return NULL;
2306
2307 /* Ought to check for null Tcl_File object... */
2308 ENTER_TCL
2309 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2310 LEAVE_TCL
2311 Py_INCREF(Py_None);
2312 return Py_None;
2313}
2314
2315static PyObject *
2316Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2317{
2318 PyObject *file;
2319 int tfile;
2320
2321 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2322 return NULL;
2323
2324#ifdef WITH_THREAD
2325 if (!self && !tcl_lock) {
2326 /* We don't have the Tcl lock since Tcl is threaded. */
2327 PyErr_SetString(PyExc_RuntimeError,
2328 "_tkinter.deletefilehandler not supported "
2329 "for threaded Tcl");
2330 return NULL;
2331 }
2332#endif
2333
2334 if (self) {
2335 CHECK_TCL_APPARTMENT;
2336 }
2337
2338 tfile = PyObject_AsFileDescriptor(file);
2339 if (tfile < 0)
2340 return NULL;
2341
2342 DeleteFHCD(tfile);
2343
2344 /* Ought to check for null Tcl_File object... */
2345 ENTER_TCL
2346 Tcl_DeleteFileHandler(tfile);
2347 LEAVE_TCL
2348 Py_INCREF(Py_None);
2349 return Py_None;
2350}
2351#endif /* HAVE_CREATEFILEHANDLER */
2352
2353
2354
2355/**** Tktt Object (timer token) ****/
2356
2357static PyTypeObject Tktt_Type;
2358
2359typedef struct {
2360 PyObject_HEAD
2361 Tcl_TimerToken token;
2362 PyObject *func;
2363} TkttObject;
2364
2365static PyObject *
2366Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2367{
2368 TkttObject *v = (TkttObject *)self;
2369 PyObject *func = v->func;
2370
2371 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2372 return NULL;
2373 if (v->token != NULL) {
2374 Tcl_DeleteTimerHandler(v->token);
2375 v->token = NULL;
2376 }
2377 if (func != NULL) {
2378 v->func = NULL;
2379 Py_DECREF(func);
2380 Py_DECREF(v); /* See Tktt_New() */
2381 }
2382 Py_INCREF(Py_None);
2383 return Py_None;
2384}
2385
2386static PyMethodDef Tktt_methods[] =
2387{
2388 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2389 {NULL, NULL}
2390};
2391
2392static TkttObject *
2393Tktt_New(PyObject *func)
2394{
2395 TkttObject *v;
2396
2397 v = PyObject_New(TkttObject, &Tktt_Type);
2398 if (v == NULL)
2399 return NULL;
2400
2401 Py_INCREF(func);
2402 v->token = NULL;
2403 v->func = func;
2404
2405 /* Extra reference, deleted when called or when handler is deleted */
2406 Py_INCREF(v);
2407 return v;
2408}
2409
2410static void
2411Tktt_Dealloc(PyObject *self)
2412{
2413 TkttObject *v = (TkttObject *)self;
2414 PyObject *func = v->func;
2415
2416 Py_XDECREF(func);
2417
2418 PyObject_Del(self);
2419}
2420
2421static PyObject *
2422Tktt_Repr(PyObject *self)
2423{
2424 TkttObject *v = (TkttObject *)self;
2425 char buf[100];
2426
2427 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2428 v->func == NULL ? ", handler deleted" : "");
2429 return PyString_FromString(buf);
2430}
2431
2432static PyObject *
2433Tktt_GetAttr(PyObject *self, char *name)
2434{
2435 return Py_FindMethod(Tktt_methods, self, name);
2436}
2437
2438static PyTypeObject Tktt_Type =
2439{
2440 PyVarObject_HEAD_INIT(NULL, 0)
2441 "tktimertoken", /*tp_name */
2442 sizeof(TkttObject), /*tp_basicsize */
2443 0, /*tp_itemsize */
2444 Tktt_Dealloc, /*tp_dealloc */
2445 0, /*tp_print */
2446 Tktt_GetAttr, /*tp_getattr */
2447 0, /*tp_setattr */
2448 0, /*tp_compare */
2449 Tktt_Repr, /*tp_repr */
2450 0, /*tp_as_number */
2451 0, /*tp_as_sequence */
2452 0, /*tp_as_mapping */
2453 0, /*tp_hash */
2454};
2455
2456
2457
2458
2459/** Timer Handler **/
2460
2461static void
2462TimerHandler(ClientData clientData)
2463{
2464 TkttObject *v = (TkttObject *)clientData;
2465 PyObject *func = v->func;
2466 PyObject *res;
2467
2468 if (func == NULL)
2469 return;
2470
2471 v->func = NULL;
2472
2473 ENTER_PYTHON
2474
2475 res = PyEval_CallObject(func, NULL);
2476 Py_DECREF(func);
2477 Py_DECREF(v); /* See Tktt_New() */
2478
2479 if (res == NULL) {
2480 errorInCmd = 1;
2481 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2482 }
2483 else
2484 Py_DECREF(res);
2485
2486 LEAVE_PYTHON
2487}
2488
2489static PyObject *
2490Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2491{
2492 int milliseconds;
2493 PyObject *func;
2494 TkttObject *v;
2495
2496 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2497 &milliseconds, &func))
2498 return NULL;
2499 if (!PyCallable_Check(func)) {
2500 PyErr_SetString(PyExc_TypeError, "bad argument list");
2501 return NULL;
2502 }
2503
2504#ifdef WITH_THREAD
2505 if (!self && !tcl_lock) {
2506 /* We don't have the Tcl lock since Tcl is threaded. */
2507 PyErr_SetString(PyExc_RuntimeError,
2508 "_tkinter.createtimerhandler not supported "
2509 "for threaded Tcl");
2510 return NULL;
2511 }
2512#endif
2513
2514 if (self) {
2515 CHECK_TCL_APPARTMENT;
2516 }
2517
2518 v = Tktt_New(func);
2519 if (v) {
2520 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2521 (ClientData)v);
2522 }
2523
2524 return (PyObject *) v;
2525}
2526
2527
2528
2529/** Event Loop **/
2530
2531static PyObject *
2532Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2533{
2534 int threshold = 0;
2535 TkappObject *self = (TkappObject*)selfptr;
2536#ifdef WITH_THREAD
2537 PyThreadState *tstate = PyThreadState_Get();
2538#endif
2539
2540 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2541 return NULL;
2542
2543#ifdef WITH_THREAD
2544 if (!self && !tcl_lock) {
2545 /* We don't have the Tcl lock since Tcl is threaded. */
2546 PyErr_SetString(PyExc_RuntimeError,
2547 "_tkinter.mainloop not supported "
2548 "for threaded Tcl");
2549 return NULL;
2550 }
2551#endif
2552
2553 if (self) {
2554 CHECK_TCL_APPARTMENT;
2555 self->dispatching = 1;
2556 }
2557
2558 quitMainLoop = 0;
2559 while (Tk_GetNumMainWindows() > threshold &&
2560 !quitMainLoop &&
2561 !errorInCmd)
2562 {
2563 int result;
2564
2565#ifdef WITH_THREAD
2566 if (self && self->threaded) {
2567 /* Allow other Python threads to run. */
2568 ENTER_TCL
2569 result = Tcl_DoOneEvent(0);
2570 LEAVE_TCL
2571 }
2572 else {
2573 Py_BEGIN_ALLOW_THREADS
2574 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2575 tcl_tstate = tstate;
2576 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2577 tcl_tstate = NULL;
2578 if(tcl_lock)PyThread_release_lock(tcl_lock);
2579 if (result == 0)
2580 Sleep(Tkinter_busywaitinterval);
2581 Py_END_ALLOW_THREADS
2582 }
2583#else
2584 result = Tcl_DoOneEvent(0);
2585#endif
2586
2587 if (PyErr_CheckSignals() != 0) {
2588 if (self)
2589 self->dispatching = 0;
2590 return NULL;
2591 }
2592 if (result < 0)
2593 break;
2594 }
2595 if (self)
2596 self->dispatching = 0;
2597 quitMainLoop = 0;
2598
2599 if (errorInCmd) {
2600 errorInCmd = 0;
2601 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2602 excInCmd = valInCmd = trbInCmd = NULL;
2603 return NULL;
2604 }
2605 Py_INCREF(Py_None);
2606 return Py_None;
2607}
2608
2609static PyObject *
2610Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2611{
2612 int flags = 0;
2613 int rv;
2614
2615 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2616 return NULL;
2617
2618 ENTER_TCL
2619 rv = Tcl_DoOneEvent(flags);
2620 LEAVE_TCL
2621 return Py_BuildValue("i", rv);
2622}
2623
2624static PyObject *
2625Tkapp_Quit(PyObject *self, PyObject *args)
2626{
2627
2628 if (!PyArg_ParseTuple(args, ":quit"))
2629 return NULL;
2630
2631 quitMainLoop = 1;
2632 Py_INCREF(Py_None);
2633 return Py_None;
2634}
2635
2636static PyObject *
2637Tkapp_InterpAddr(PyObject *self, PyObject *args)
2638{
2639
2640 if (!PyArg_ParseTuple(args, ":interpaddr"))
2641 return NULL;
2642
2643 return PyInt_FromLong((long)Tkapp_Interp(self));
2644}
2645
2646static PyObject *
2647Tkapp_TkInit(PyObject *self, PyObject *args)
2648{
2649 static int has_failed;
2650 Tcl_Interp *interp = Tkapp_Interp(self);
2651 Tk_Window main_window;
2652 const char * _tk_exists = NULL;
2653 int err;
2654 main_window = Tk_MainWindow(interp);
2655
2656 /* In all current versions of Tk (including 8.4.13), Tk_Init
2657 deadlocks on the second call when the first call failed.
2658 To avoid the deadlock, we just refuse the second call through
2659 a static variable. */
2660 if (has_failed) {
2661 PyErr_SetString(Tkinter_TclError,
2662 "Calling Tk_Init again after a previous call failed might deadlock");
2663 return NULL;
2664 }
2665
2666 /* We want to guard against calling Tk_Init() multiple times */
2667 CHECK_TCL_APPARTMENT;
2668 ENTER_TCL
2669 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2670 ENTER_OVERLAP
2671 if (err == TCL_ERROR) {
2672 /* This sets an exception, but we cannot return right
2673 away because we need to exit the overlap first. */
2674 Tkinter_Error(self);
2675 } else {
2676 _tk_exists = Tkapp_Result(self);
2677 }
2678 LEAVE_OVERLAP_TCL
2679 if (err == TCL_ERROR) {
2680 return NULL;
2681 }
2682 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2683 if (Tk_Init(interp) == TCL_ERROR) {
2684 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2685 has_failed = 1;
2686 return NULL;
2687 }
2688 }
2689 Py_INCREF(Py_None);
2690 return Py_None;
2691}
2692
2693static PyObject *
2694Tkapp_WantObjects(PyObject *self, PyObject *args)
2695{
2696
2697 int wantobjects = -1;
2698 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2699 return NULL;
2700 if (wantobjects == -1)
2701 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2702 ((TkappObject*)self)->wantobjects = wantobjects;
2703
2704 Py_INCREF(Py_None);
2705 return Py_None;
2706}
2707
2708static PyObject *
2709Tkapp_WillDispatch(PyObject *self, PyObject *args)
2710{
2711
2712 ((TkappObject*)self)->dispatching = 1;
2713
2714 Py_INCREF(Py_None);
2715 return Py_None;
2716}
2717
2718
2719
2720/**** Tkapp Method List ****/
2721
2722static PyMethodDef Tkapp_methods[] =
2723{
2724 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2725 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2726 {"call", Tkapp_Call, METH_VARARGS},
2727 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2728 {"eval", Tkapp_Eval, METH_VARARGS},
2729 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2730 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2731 {"record", Tkapp_Record, METH_VARARGS},
2732 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2733 {"setvar", Tkapp_SetVar, METH_VARARGS},
2734 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2735 {"getvar", Tkapp_GetVar, METH_VARARGS},
2736 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2737 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2738 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2739 {"getint", Tkapp_GetInt, METH_VARARGS},
2740 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2741 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2742 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2743 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2744 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2745 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2746 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2747 {"split", Tkapp_Split, METH_VARARGS},
2748 {"merge", Tkapp_Merge, METH_VARARGS},
2749 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2750 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2751#ifdef HAVE_CREATEFILEHANDLER
2752 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2753 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2754#endif
2755 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2756 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2757 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2758 {"quit", Tkapp_Quit, METH_VARARGS},
2759 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2760 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2761 {NULL, NULL}
2762};
2763
2764
2765
2766
2767/**** Tkapp Type Methods ****/
2768
2769static void
2770Tkapp_Dealloc(PyObject *self)
2771{
2772 /*CHECK_TCL_APPARTMENT;*/
2773 ENTER_TCL
2774 Tcl_DeleteInterp(Tkapp_Interp(self));
2775 LEAVE_TCL
2776 PyObject_Del(self);
2777 DisableEventHook();
2778}
2779
2780static PyObject *
2781Tkapp_GetAttr(PyObject *self, char *name)
2782{
2783 return Py_FindMethod(Tkapp_methods, self, name);
2784}
2785
2786static PyTypeObject Tkapp_Type =
2787{
2788 PyVarObject_HEAD_INIT(NULL, 0)
2789 "tkapp", /*tp_name */
2790 sizeof(TkappObject), /*tp_basicsize */
2791 0, /*tp_itemsize */
2792 Tkapp_Dealloc, /*tp_dealloc */
2793 0, /*tp_print */
2794 Tkapp_GetAttr, /*tp_getattr */
2795 0, /*tp_setattr */
2796 0, /*tp_compare */
2797 0, /*tp_repr */
2798 0, /*tp_as_number */
2799 0, /*tp_as_sequence */
2800 0, /*tp_as_mapping */
2801 0, /*tp_hash */
2802};
2803
2804
2805
2806
2807/**** Tkinter Module ****/
2808
2809typedef struct {
2810 PyObject* tuple;
2811 int size; /* current size */
2812 int maxsize; /* allocated size */
2813} FlattenContext;
2814
2815static int
2816_bump(FlattenContext* context, int size)
2817{
2818 /* expand tuple to hold (at least) size new items.
2819 return true if successful, false if an exception was raised */
2820
2821 int maxsize = context->maxsize * 2;
2822
2823 if (maxsize < context->size + size)
2824 maxsize = context->size + size;
2825
2826 context->maxsize = maxsize;
2827
2828 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2829}
2830
2831static int
2832_flatten1(FlattenContext* context, PyObject* item, int depth)
2833{
2834 /* add tuple or list to argument tuple (recursively) */
2835
2836 int i, size;
2837
2838 if (depth > 1000) {
2839 PyErr_SetString(PyExc_ValueError,
2840 "nesting too deep in _flatten");
2841 return 0;
2842 } else if (PyList_Check(item)) {
2843 size = PyList_GET_SIZE(item);
2844 /* preallocate (assume no nesting) */
2845 if (context->size + size > context->maxsize &&
2846 !_bump(context, size))
2847 return 0;
2848 /* copy items to output tuple */
2849 for (i = 0; i < size; i++) {
2850 PyObject *o = PyList_GET_ITEM(item, i);
2851 if (PyList_Check(o) || PyTuple_Check(o)) {
2852 if (!_flatten1(context, o, depth + 1))
2853 return 0;
2854 } else if (o != Py_None) {
2855 if (context->size + 1 > context->maxsize &&
2856 !_bump(context, 1))
2857 return 0;
2858 Py_INCREF(o);
2859 PyTuple_SET_ITEM(context->tuple,
2860 context->size++, o);
2861 }
2862 }
2863 } else if (PyTuple_Check(item)) {
2864 /* same, for tuples */
2865 size = PyTuple_GET_SIZE(item);
2866 if (context->size + size > context->maxsize &&
2867 !_bump(context, size))
2868 return 0;
2869 for (i = 0; i < size; i++) {
2870 PyObject *o = PyTuple_GET_ITEM(item, i);
2871 if (PyList_Check(o) || PyTuple_Check(o)) {
2872 if (!_flatten1(context, o, depth + 1))
2873 return 0;
2874 } else if (o != Py_None) {
2875 if (context->size + 1 > context->maxsize &&
2876 !_bump(context, 1))
2877 return 0;
2878 Py_INCREF(o);
2879 PyTuple_SET_ITEM(context->tuple,
2880 context->size++, o);
2881 }
2882 }
2883 } else {
2884 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2885 return 0;
2886 }
2887 return 1;
2888}
2889
2890static PyObject *
2891Tkinter_Flatten(PyObject* self, PyObject* args)
2892{
2893 FlattenContext context;
2894 PyObject* item;
2895
2896 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2897 return NULL;
2898
2899 context.maxsize = PySequence_Size(item);
2900 if (context.maxsize <= 0)
2901 return PyTuple_New(0);
2902
2903 context.tuple = PyTuple_New(context.maxsize);
2904 if (!context.tuple)
2905 return NULL;
2906
2907 context.size = 0;
2908
2909 if (!_flatten1(&context, item,0))
2910 return NULL;
2911
2912 if (_PyTuple_Resize(&context.tuple, context.size))
2913 return NULL;
2914
2915 return context.tuple;
2916}
2917
2918static PyObject *
2919Tkinter_Create(PyObject *self, PyObject *args)
2920{
2921 char *screenName = NULL;
2922 char *baseName = NULL;
2923 char *className = NULL;
2924 int interactive = 0;
2925 int wantobjects = 0;
2926 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2927 int sync = 0; /* pass -sync to wish */
2928 char *use = NULL; /* pass -use to wish */
2929
2930 baseName = strrchr(Py_GetProgramName(), '/');
2931 if (baseName != NULL)
2932 baseName++;
2933 else
2934 baseName = Py_GetProgramName();
2935 className = "Tk";
2936
2937 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2938 &screenName, &baseName, &className,
2939 &interactive, &wantobjects, &wantTk,
2940 &sync, &use))
2941 return NULL;
2942
2943 return (PyObject *) Tkapp_New(screenName, baseName, className,
2944 interactive, wantobjects, wantTk,
2945 sync, use);
2946}
2947
2948static PyObject *
2949Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2950{
2951 int new_val;
2952 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2953 return NULL;
2954 if (new_val < 0) {
2955 PyErr_SetString(PyExc_ValueError,
2956 "busywaitinterval must be >= 0");
2957 return NULL;
2958 }
2959 Tkinter_busywaitinterval = new_val;
2960 Py_INCREF(Py_None);
2961 return Py_None;
2962}
2963
2964static char setbusywaitinterval_doc[] =
2965"setbusywaitinterval(n) -> None\n\
2966\n\
2967Set the busy-wait interval in milliseconds between successive\n\
2968calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2969It should be set to a divisor of the maximum time between\n\
2970frames in an animation.";
2971
2972static PyObject *
2973Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2974{
2975 return PyInt_FromLong(Tkinter_busywaitinterval);
2976}
2977
2978static char getbusywaitinterval_doc[] =
2979"getbusywaitinterval() -> int\n\
2980\n\
2981Return the current busy-wait interval between successive\n\
2982calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2983
2984static PyMethodDef moduleMethods[] =
2985{
2986 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2987 {"create", Tkinter_Create, METH_VARARGS},
2988#ifdef HAVE_CREATEFILEHANDLER
2989 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2990 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2991#endif
2992 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2993 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2994 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2995 {"quit", Tkapp_Quit, METH_VARARGS},
2996 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2997 setbusywaitinterval_doc},
2998 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2999 METH_NOARGS, getbusywaitinterval_doc},
3000 {NULL, NULL}
3001};
3002
3003#ifdef WAIT_FOR_STDIN
3004
3005static int stdin_ready = 0;
3006
3007#ifndef MS_WINDOWS
3008static void
3009MyFileProc(void *clientData, int mask)
3010{
3011 stdin_ready = 1;
3012}
3013#endif
3014
3015#ifdef WITH_THREAD
3016static PyThreadState *event_tstate = NULL;
3017#endif
3018
3019static int
3020EventHook(void)
3021{
3022#ifndef MS_WINDOWS
3023 int tfile;
3024#endif
3025#ifdef WITH_THREAD
3026 PyEval_RestoreThread(event_tstate);
3027#endif
3028 stdin_ready = 0;
3029 errorInCmd = 0;
3030#ifndef MS_WINDOWS
3031 tfile = fileno(stdin);
3032 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3033#endif
3034 while (!errorInCmd && !stdin_ready) {
3035 int result;
3036#ifdef MS_WINDOWS
3037 if (_kbhit()) {
3038 stdin_ready = 1;
3039 break;
3040 }
3041#endif
3042#if defined(WITH_THREAD) || defined(MS_WINDOWS)
3043 Py_BEGIN_ALLOW_THREADS
3044 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3045 tcl_tstate = event_tstate;
3046
3047 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3048
3049 tcl_tstate = NULL;
3050 if(tcl_lock)PyThread_release_lock(tcl_lock);
3051 if (result == 0)
3052 Sleep(Tkinter_busywaitinterval);
3053 Py_END_ALLOW_THREADS
3054#else
3055 result = Tcl_DoOneEvent(0);
3056#endif
3057
3058 if (result < 0)
3059 break;
3060 }
3061#ifndef MS_WINDOWS
3062 Tcl_DeleteFileHandler(tfile);
3063#endif
3064 if (errorInCmd) {
3065 errorInCmd = 0;
3066 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3067 excInCmd = valInCmd = trbInCmd = NULL;
3068 PyErr_Print();
3069 }
3070#ifdef WITH_THREAD
3071 PyEval_SaveThread();
3072#endif
3073 return 0;
3074}
3075
3076#endif
3077
3078static void
3079EnableEventHook(void)
3080{
3081#ifdef WAIT_FOR_STDIN
3082 if (PyOS_InputHook == NULL) {
3083#ifdef WITH_THREAD
3084 event_tstate = PyThreadState_Get();
3085#endif
3086 PyOS_InputHook = EventHook;
3087 }
3088#endif
3089}
3090
3091static void
3092DisableEventHook(void)
3093{
3094#ifdef WAIT_FOR_STDIN
3095 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3096 PyOS_InputHook = NULL;
3097 }
3098#endif
3099}
3100
3101
3102/* all errors will be checked in one fell swoop in init_tkinter() */
3103static void
3104ins_long(PyObject *d, char *name, long val)
3105{
3106 PyObject *v = PyInt_FromLong(val);
3107 if (v) {
3108 PyDict_SetItemString(d, name, v);
3109 Py_DECREF(v);
3110 }
3111}
3112static void
3113ins_string(PyObject *d, char *name, char *val)
3114{
3115 PyObject *v = PyString_FromString(val);
3116 if (v) {
3117 PyDict_SetItemString(d, name, v);
3118 Py_DECREF(v);
3119 }
3120}
3121
3122
3123PyMODINIT_FUNC
3124init_tkinter(void)
3125{
3126 PyObject *m, *d;
3127
3128 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3129
3130#ifdef WITH_THREAD
3131 tcl_lock = PyThread_allocate_lock();
3132#endif
3133
3134 m = Py_InitModule("_tkinter", moduleMethods);
3135 if (m == NULL)
3136 return;
3137
3138 d = PyModule_GetDict(m);
3139 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3140 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3141
3142 ins_long(d, "READABLE", TCL_READABLE);
3143 ins_long(d, "WRITABLE", TCL_WRITABLE);
3144 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3145 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3146 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3147 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3148 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3149 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3150 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3151 ins_string(d, "TK_VERSION", TK_VERSION);
3152 ins_string(d, "TCL_VERSION", TCL_VERSION);
3153
3154 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3155
3156 Py_TYPE(&Tktt_Type) = &PyType_Type;
3157 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3158
3159 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3160 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3161
3162#ifdef TK_AQUA
3163 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3164 * start waking up. Note that Tcl_FindExecutable will do this, this
3165 * code must be above it! The original warning from
3166 * tkMacOSXAppInit.c is copied below.
3167 *
3168 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3169 * Tcl interpreter for now. It probably should work to do this
3170 * in the other order, but for now it doesn't seem to.
3171 *
3172 */
3173 Tk_MacOSXSetupTkNotifier();
3174#endif
3175
3176
3177 /* This helps the dynamic loader; in Unicode aware Tcl versions
3178 it also helps Tcl find its encodings. */
3179 Tcl_FindExecutable(Py_GetProgramName());
3180
3181 if (PyErr_Occurred())
3182 return;
3183
3184#if 0
3185 /* This was not a good idea; through <Destroy> bindings,
3186 Tcl_Finalize() may invoke Python code but at that point the
3187 interpreter and thread state have already been destroyed! */
3188 Py_AtExit(Tcl_Finalize);
3189#endif
3190
3191}
Note: See TracBrowser for help on using the repository browser.