ยปCore Development>Code coverage>Modules/_tkinter.c

Python code coverage for Modules/_tkinter.c

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