~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Modules/_tkinter.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

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