home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Misc / RPM / Tkinter / src / _tkinter.c next >
Encoding:
C/C++ Source or Header  |  2000-10-16  |  47.0 KB  |  2,253 lines

  1. /***********************************************************
  2. Copyright (C) 1994 Steen Lumholt.
  3.  
  4.                         All Rights Reserved
  5.  
  6. ******************************************************************/
  7.  
  8. /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
  9.  
  10. /* TCL/TK VERSION INFO:
  11.  
  12.     Only Tcl/Tk 8.0 and later are supported.  Older versions are not
  13.     supported.  (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
  14.     libraries.)
  15. */
  16.  
  17. /* XXX Further speed-up ideas, involving Tcl 8.0 features:
  18.  
  19.    - In Tcl_Call(), create Tcl objects from the arguments, possibly using
  20.    intelligent mappings between Python objects and Tcl objects (e.g. ints,
  21.    floats and Tcl window pointers could be handled specially).
  22.  
  23.    - Register a new Tcl type, "Python callable", which can be called more
  24.    efficiently and passed to Tcl_EvalObj() directly (if this is possible).
  25.  
  26. */
  27.  
  28.  
  29. #include "Python.h"
  30. #include <ctype.h>
  31.  
  32. #ifdef WITH_THREAD
  33. #include "pythread.h"
  34. #endif
  35.  
  36. #ifdef MS_WINDOWS
  37. #include <windows.h>
  38. #endif
  39.  
  40. #ifdef macintosh
  41. #define MAC_TCL
  42. #endif
  43.  
  44. #include <tcl.h>
  45. #include <tk.h>
  46.  
  47. #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
  48.  
  49. #if TKMAJORMINOR < 8000
  50. #error "Tk older than 8.0 not supported"
  51. #endif
  52.  
  53. #if defined(macintosh)
  54. /* Sigh, we have to include this to get at the tcl qd pointer */
  55. #include <tkMac.h>
  56. /* And this one we need to clear the menu bar */
  57. #include <Menus.h>
  58. #endif
  59.  
  60. #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
  61. #define HAVE_CREATEFILEHANDLER
  62. #endif
  63.  
  64. #ifdef HAVE_CREATEFILEHANDLER
  65.  
  66. /* Tcl_CreateFileHandler() changed several times; these macros deal with the
  67.    messiness.  In Tcl 8.0 and later, it is not available on Windows (and on
  68.    Unix, only because Jack added it back); when available on Windows, it only
  69.    applies to sockets. */
  70.  
  71. #ifdef MS_WINDOWS
  72. #define FHANDLETYPE TCL_WIN_SOCKET
  73. #else
  74. #define FHANDLETYPE TCL_UNIX_FD
  75. #endif
  76.  
  77. /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
  78.    which uses this to handle Tcl events while the user is typing commands. */
  79.  
  80. #if FHANDLETYPE == TCL_UNIX_FD
  81. #define WAIT_FOR_STDIN
  82. #endif
  83.  
  84. #endif /* HAVE_CREATEFILEHANDLER */
  85.  
  86. #ifdef MS_WINDOWS
  87. #include <conio.h>
  88. #define WAIT_FOR_STDIN
  89. #endif
  90.  
  91. #ifdef WITH_THREAD
  92.  
  93. /* The threading situation is complicated.  Tcl is not thread-safe, except for
  94.    Tcl 8.1, which will probably remain in alpha status for another 6 months
  95.    (and the README says that Tk will probably remain thread-unsafe forever).
  96.    So we need to use a lock around all uses of Tcl.  Previously, the Python
  97.    interpreter lock was used for this.  However, this causes problems when
  98.    other Python threads need to run while Tcl is blocked waiting for events.
  99.  
  100.    To solve this problem, a separate lock for Tcl is introduced.  Holding it
  101.    is incompatible with holding Python's interpreter lock.  The following four
  102.    macros manipulate both locks together.
  103.  
  104.    ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
  105.    Py_END_ALLOW_THREADS.  They should be used whenever a call into Tcl is made
  106.    that could call an event handler, or otherwise affect the state of a Tcl
  107.    interpreter.  These assume that the surrounding code has the Python
  108.    interpreter lock; inside the brackets, the Python interpreter lock has been 
  109.    released and the lock for Tcl has been acquired.
  110.  
  111.    Sometimes, it is necessary to have both the Python lock and the Tcl lock.
  112.    (For example, when transferring data from the Tcl interpreter result to a
  113.    Python string object.)  This can be done by using different macros to close
  114.    the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
  115.    the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
  116.    releases the Tcl lock.
  117.  
  118.    By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
  119.    handlers when the handler needs to use Python.  Such event handlers are
  120.    entered while the lock for Tcl is held; the event handler presumably needs
  121.    to use Python.  ENTER_PYTHON releases the lock for Tcl and acquires
  122.    the Python interpreter lock, restoring the appropriate thread state, and
  123.    LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
  124.    for Tcl.  It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
  125.    the code between ENTER_PYTHON and LEAVE_PYTHON.
  126.  
  127.    These locks expand to several statements and brackets; they should not be
  128.    used in branches of if statements and the like.
  129.  
  130. */
  131.  
  132. static PyThread_type_lock tcl_lock = 0;
  133. static PyThreadState *tcl_tstate = NULL;
  134.  
  135. #define ENTER_TCL \
  136.     { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
  137.         PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
  138.  
  139. #define LEAVE_TCL \
  140.     tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
  141.  
  142. #define ENTER_OVERLAP \
  143.     Py_END_ALLOW_THREADS
  144.  
  145. #define LEAVE_OVERLAP_TCL \
  146.     tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
  147.  
  148. #define ENTER_PYTHON \
  149.     { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
  150.             PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
  151.  
  152. #define LEAVE_PYTHON \
  153.     { PyThreadState *tstate = PyEval_SaveThread(); \
  154.             PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
  155.  
  156. #else
  157.  
  158. #define ENTER_TCL
  159. #define LEAVE_TCL
  160. #define ENTER_OVERLAP
  161. #define LEAVE_OVERLAP_TCL
  162. #define ENTER_PYTHON
  163. #define LEAVE_PYTHON
  164.  
  165. #endif
  166.  
  167. #ifdef macintosh
  168.  
  169. /*
  170. ** Additional cruft needed by Tcl/Tk on the Mac.
  171. ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
  172. */
  173.  
  174. /* ckfree() expects a char* */
  175. #define FREECAST (char *)
  176.  
  177. #include <Events.h> /* For EventRecord */
  178.  
  179. typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
  180. void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
  181. int TkMacConvertEvent(EventRecord *eventPtr);
  182.  
  183. staticforward int PyMacConvertEvent(EventRecord *eventPtr);
  184.  
  185. #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
  186.     #pragma import on
  187. #endif
  188.  
  189. #include <SIOUX.h>
  190. extern int SIOUXIsAppWindow(WindowPtr);
  191.  
  192. #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
  193.     #pragma import reset
  194. #endif
  195. #endif /* macintosh */
  196.  
  197. #ifndef FREECAST
  198. #define FREECAST (char *)
  199. #endif
  200.  
  201. /**** Tkapp Object Declaration ****/
  202.  
  203. staticforward PyTypeObject Tkapp_Type;
  204.  
  205. typedef struct {
  206.     PyObject_HEAD
  207.     Tcl_Interp *interp;
  208. } TkappObject;
  209.  
  210. #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
  211. #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
  212. #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
  213.  
  214. #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
  215. (void *) v, ((PyObject *) v)->ob_refcnt))
  216.  
  217.  
  218.  
  219. /**** Error Handling ****/
  220.  
  221. static PyObject *Tkinter_TclError;
  222. static int quitMainLoop = 0;
  223. static int errorInCmd = 0;
  224. static PyObject *excInCmd;
  225. static PyObject *valInCmd;
  226. static PyObject *trbInCmd;
  227.  
  228.  
  229.  
  230. static PyObject *
  231. Tkinter_Error(PyObject *v)
  232. {
  233.     PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
  234.     return NULL;
  235. }
  236.  
  237.  
  238.  
  239. /**** Utils ****/
  240.  
  241. #ifdef WITH_THREAD
  242. #ifndef MS_WINDOWS
  243.  
  244. /* Millisecond sleep() for Unix platforms. */
  245.  
  246. static void
  247. Sleep(int milli)
  248. {
  249.     /* XXX Too bad if you don't have select(). */
  250.     struct timeval t;
  251.     t.tv_sec = milli/1000;
  252.     t.tv_usec = (milli%1000) * 1000;
  253.     select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  254. }
  255. #endif /* MS_WINDOWS */
  256. #endif /* WITH_THREAD */
  257.  
  258.  
  259. static char *
  260. AsString(PyObject *value, PyObject *tmp)
  261. {
  262.     if (PyString_Check(value))
  263.         return PyString_AsString(value);
  264.     else if (PyUnicode_Check(value)) {
  265.         PyObject *v = PyUnicode_AsUTF8String(value);
  266.         if (v == NULL)
  267.             return NULL;
  268.         if (PyList_Append(tmp, v) != 0) {
  269.             Py_DECREF(v);
  270.             return NULL;
  271.         }
  272.         Py_DECREF(v);
  273.         return PyString_AsString(v);
  274.     }
  275.     else {
  276.         PyObject *v = PyObject_Str(value);
  277.         if (v == NULL)
  278.             return NULL;
  279.         if (PyList_Append(tmp, v) != 0) {
  280.             Py_DECREF(v);
  281.             return NULL;
  282.         }
  283.         Py_DECREF(v);
  284.         return PyString_AsString(v);
  285.     }
  286. }
  287.  
  288.  
  289.  
  290. #define ARGSZ 64
  291.  
  292. static char *
  293. Merge(PyObject *args)
  294. {
  295.     PyObject *tmp = NULL;
  296.     char *argvStore[ARGSZ];
  297.     char **argv = NULL;
  298.     int fvStore[ARGSZ];
  299.     int *fv = NULL;
  300.     int argc = 0, fvc = 0, i;
  301.     char *res = NULL;
  302.  
  303.     if (!(tmp = PyList_New(0)))
  304.         return NULL;
  305.  
  306.     argv = argvStore;
  307.     fv = fvStore;
  308.  
  309.     if (args == NULL)
  310.         argc = 0;
  311.  
  312.     else if (!PyTuple_Check(args)) {
  313.         argc = 1;
  314.         fv[0] = 0;
  315.         if (!(argv[0] = AsString(args, tmp)))
  316.             goto finally;
  317.     }
  318.     else {
  319.         argc = PyTuple_Size(args);
  320.  
  321.         if (argc > ARGSZ) {
  322.             argv = (char **)ckalloc(argc * sizeof(char *));
  323.             fv = (int *)ckalloc(argc * sizeof(int));
  324.             if (argv == NULL || fv == NULL) {
  325.                 PyErr_NoMemory();
  326.                 goto finally;
  327.             }
  328.         }
  329.  
  330.         for (i = 0; i < argc; i++) {
  331.             PyObject *v = PyTuple_GetItem(args, i);
  332.             if (PyTuple_Check(v)) {
  333.                 fv[i] = 1;
  334.                 if (!(argv[i] = Merge(v)))
  335.                     goto finally;
  336.                 fvc++;
  337.             }
  338.             else if (v == Py_None) {
  339.                 argc = i;
  340.                 break;
  341.             }
  342.             else {
  343.                 fv[i] = 0;
  344.                 if (!(argv[i] = AsString(v, tmp)))
  345.                     goto finally;
  346.                 fvc++;
  347.             }
  348.         }
  349.     }
  350.     res = Tcl_Merge(argc, argv);
  351.     if (res == NULL)
  352.         PyErr_SetString(Tkinter_TclError, "merge failed");
  353.  
  354.   finally:
  355.     for (i = 0; i < fvc; i++)
  356.         if (fv[i]) {
  357.             ckfree(argv[i]);
  358.         }
  359.     if (argv != argvStore)
  360.         ckfree(FREECAST argv);
  361.     if (fv != fvStore)
  362.         ckfree(FREECAST fv);
  363.  
  364.     Py_DECREF(tmp);
  365.     return res;
  366. }
  367.  
  368.  
  369.  
  370. static PyObject *
  371. Split(char *list)
  372. {
  373.     int argc;
  374.     char **argv;
  375.     PyObject *v;
  376.  
  377.     if (list == NULL) {
  378.         Py_INCREF(Py_None);
  379.         return Py_None;
  380.     }
  381.  
  382.     if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
  383.         /* Not a list.
  384.          * Could be a quoted string containing funnies, e.g. {"}.
  385.          * Return the string itself.
  386.          */
  387.         return PyString_FromString(list);
  388.     }
  389.  
  390.     if (argc == 0)
  391.         v = PyString_FromString("");
  392.     else if (argc == 1)
  393.         v = PyString_FromString(argv[0]);
  394.     else if ((v = PyTuple_New(argc)) != NULL) {
  395.         int i;
  396.         PyObject *w;
  397.  
  398.         for (i = 0; i < argc; i++) {
  399.             if ((w = Split(argv[i])) == NULL) {
  400.                 Py_DECREF(v);
  401.                 v = NULL;
  402.                 break;
  403.             }
  404.             PyTuple_SetItem(v, i, w);
  405.         }
  406.     }
  407.     Tcl_Free(FREECAST argv);
  408.     return v;
  409. }
  410.  
  411.  
  412.  
  413. /**** Tkapp Object ****/
  414.  
  415. #ifndef WITH_APPINIT
  416. int
  417. Tcl_AppInit(Tcl_Interp *interp)
  418. {
  419.     Tk_Window main;
  420.  
  421.     main = Tk_MainWindow(interp);
  422.     if (Tcl_Init(interp) == TCL_ERROR) {
  423.         PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
  424.         return TCL_ERROR;
  425.     }
  426.     if (Tk_Init(interp) == TCL_ERROR) {
  427.         PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
  428.         return TCL_ERROR;
  429.     }
  430.     return TCL_OK;
  431. }
  432. #endif /* !WITH_APPINIT */
  433.  
  434.  
  435.  
  436.  
  437. /* Initialize the Tk application; see the `main' function in
  438.  * `tkMain.c'.
  439.  */
  440.  
  441. static void EnableEventHook(void); /* Forward */
  442. static void DisableEventHook(void); /* Forward */
  443.  
  444. static TkappObject *
  445. Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
  446. {
  447.     TkappObject *v;
  448.     char *argv0;
  449.   
  450.     v = PyObject_New(TkappObject, &Tkapp_Type);
  451.     if (v == NULL)
  452.         return NULL;
  453.  
  454.     v->interp = Tcl_CreateInterp();
  455.  
  456. #if defined(macintosh)
  457.     /* This seems to be needed */
  458.     ClearMenuBar();
  459.     TkMacInitMenus(v->interp);
  460. #endif
  461.     /* Delete the 'exit' command, which can screw things up */
  462.     Tcl_DeleteCommand(v->interp, "exit");
  463.  
  464.     if (screenName != NULL)
  465.         Tcl_SetVar2(v->interp, "env", "DISPLAY",
  466.                 screenName, TCL_GLOBAL_ONLY);
  467.  
  468.     if (interactive)
  469.         Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
  470.     else
  471.         Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
  472.  
  473.     /* This is used to get the application class for Tk 4.1 and up */
  474.     argv0 = (char*)ckalloc(strlen(className) + 1);
  475.     if (!argv0) {
  476.         PyErr_NoMemory();
  477.         Py_DECREF(v);
  478.         return NULL;
  479.     }
  480.  
  481.     strcpy(argv0, className);
  482.     if (isupper((int)(argv0[0])))
  483.         argv0[0] = tolower(argv0[0]);
  484.     Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
  485.     ckfree(argv0);
  486.  
  487.     if (Tcl_AppInit(v->interp) != TCL_OK)
  488.         return (TkappObject *)Tkinter_Error((PyObject *)v);
  489.  
  490.     EnableEventHook();
  491.  
  492.     return v;
  493. }
  494.  
  495.  
  496.  
  497. /** Tcl Eval **/
  498.  
  499. #if TKMAJORMINOR >= 8001
  500. #define USING_OBJECTS
  501. #endif
  502.  
  503. #ifdef USING_OBJECTS
  504.  
  505. static Tcl_Obj*
  506. AsObj(PyObject *value)
  507. {
  508.     Tcl_Obj *result;
  509.  
  510.     if (PyString_Check(value))
  511.         return Tcl_NewStringObj(PyString_AS_STRING(value),
  512.                     PyString_GET_SIZE(value));
  513.     else if (PyInt_Check(value))
  514.         return Tcl_NewLongObj(PyInt_AS_LONG(value));
  515.     else if (PyFloat_Check(value))
  516.         return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
  517.     else if (PyTuple_Check(value)) {
  518.         Tcl_Obj **argv = (Tcl_Obj**)
  519.             ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
  520.         int i;
  521.         if(!argv)
  522.           return 0;
  523.         for(i=0;i<PyTuple_Size(value);i++)
  524.           argv[i] = AsObj(PyTuple_GetItem(value,i));
  525.         result = Tcl_NewListObj(PyTuple_Size(value), argv);
  526.         ckfree(FREECAST argv);
  527.         return result;
  528.     }
  529.     else if (PyUnicode_Check(value)) {
  530. #if TKMAJORMINOR <= 8001
  531.         /* In Tcl 8.1 we must use UTF-8 */
  532.         PyObject* utf8 = PyUnicode_AsUTF8String(value);
  533.         if (!utf8)
  534.             return 0;
  535.         result = Tcl_NewStringObj(PyString_AS_STRING(utf8),
  536.                       PyString_GET_SIZE(utf8));
  537.         Py_DECREF(utf8);
  538.         return result;
  539. #else /* TKMAJORMINOR > 8001 */
  540.         /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
  541.         if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
  542.             /* XXX Should really test this at compile time */
  543.             PyErr_SetString(PyExc_SystemError,
  544.                 "Py_UNICODE and Tcl_UniChar differ in size");
  545.             return 0;
  546.         }
  547.         return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
  548.                      PyUnicode_GET_SIZE(value));
  549. #endif /* TKMAJORMINOR > 8001 */
  550.     }
  551.     else {
  552.         PyObject *v = PyObject_Str(value);
  553.         if (!v)
  554.             return 0;
  555.         result = AsObj(v);
  556.         Py_DECREF(v);
  557.         return result;
  558.     }
  559. }
  560.  
  561. static PyObject *
  562. Tkapp_Call(PyObject *self, PyObject *args)
  563. {
  564.     Tcl_Obj *objStore[ARGSZ];
  565.     Tcl_Obj **objv = NULL;
  566.     int objc = 0, i;
  567.     PyObject *res = NULL;
  568.     Tcl_Interp *interp = Tkapp_Interp(self);
  569.     /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
  570.     int flags = TCL_EVAL_DIRECT;
  571.  
  572.     objv = objStore;
  573.  
  574.     if (args == NULL)
  575.         objc = 0;
  576.  
  577.     else if (!PyTuple_Check(args)) {
  578.         objc = 1;
  579.         objv[0] = AsObj(args);
  580.         if (objv[0] == 0)
  581.             goto finally;
  582.         Tcl_IncrRefCount(objv[0]);
  583.     }
  584.     else {
  585.         objc = PyTuple_Size(args);
  586.  
  587.         if (objc > ARGSZ) {
  588.             objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
  589.             if (objv == NULL) {
  590.                 PyErr_NoMemory();
  591.                 goto finally;
  592.             }
  593.         }
  594.  
  595.         for (i = 0; i < objc; i++) {
  596.             PyObject *v = PyTuple_GetItem(args, i);
  597.             if (v == Py_None) {
  598.                 objc = i;
  599.                 break;
  600.             }
  601.             objv[i] = AsObj(v);
  602.             if (!objv[i])
  603.                 goto finally;
  604.             Tcl_IncrRefCount(objv[i]);
  605.         }
  606.     }
  607.  
  608.     ENTER_TCL
  609.  
  610.     i = Tcl_EvalObjv(interp, objc, objv, flags);
  611.  
  612.     ENTER_OVERLAP
  613.     if (i == TCL_ERROR)
  614.         Tkinter_Error(self);
  615.     else {
  616.         /* We could request the object result here, but doing
  617.            so would confuse applications that expect a string. */
  618.         char *s = Tcl_GetStringResult(interp);
  619.         char *p = s;
  620.         /* If the result contains any bytes with the top bit set,
  621.            it's UTF-8 and we should decode it to Unicode */
  622.         while (*p != '\0') {
  623.             if (*p & 0x80)
  624.                 break;
  625.             p++;
  626.         }
  627.         if (*p == '\0')
  628.             res = PyString_FromStringAndSize(s, (int)(p-s));
  629.         else {
  630.             /* Convert UTF-8 to Unicode string */
  631.             p = strchr(p, '\0');
  632.             res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
  633.             if (res == NULL) {
  634.                 PyErr_Clear();
  635.                 res = PyString_FromStringAndSize(s, (int)(p-s));
  636.             }
  637.         }
  638.     }
  639.  
  640.     LEAVE_OVERLAP_TCL
  641.  
  642.   finally:
  643.     for (i = 0; i < objc; i++)
  644.         Tcl_DecrRefCount(objv[i]);
  645.     if (objv != objStore)
  646.         ckfree(FREECAST objv);
  647.     return res;
  648. }
  649.  
  650. #else /* !USING_OBJECTS */
  651.  
  652. static PyObject *
  653. Tkapp_Call(PyObject *self, PyObject *args)
  654. {
  655.     /* This is copied from Merge() */
  656.     PyObject *tmp = NULL;
  657.     char *argvStore[ARGSZ];
  658.     char **argv = NULL;
  659.     int fvStore[ARGSZ];
  660.     int *fv = NULL;
  661.     int argc = 0, fvc = 0, i;
  662.     PyObject *res = NULL; /* except this has a different type */
  663.     Tcl_CmdInfo info; /* and this is added */
  664.     Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
  665.  
  666.     if (!(tmp = PyList_New(0)))
  667.         return NULL;
  668.  
  669.     argv = argvStore;
  670.     fv = fvStore;
  671.  
  672.     if (args == NULL)
  673.         argc = 0;
  674.  
  675.     else if (!PyTuple_Check(args)) {
  676.         argc = 1;
  677.         fv[0] = 0;
  678.         if (!(argv[0] = AsString(args, tmp)))
  679.             goto finally;
  680.     }
  681.     else {
  682.         argc = PyTuple_Size(args);
  683.  
  684.         if (argc > ARGSZ) {
  685.             argv = (char **)ckalloc(argc * sizeof(char *));
  686.             fv = (int *)ckalloc(argc * sizeof(int));
  687.             if (argv == NULL || fv == NULL) {
  688.                 PyErr_NoMemory();
  689.                 goto finally;
  690.             }
  691.         }
  692.  
  693.         for (i = 0; i < argc; i++) {
  694.             PyObject *v = PyTuple_GetItem(args, i);
  695.             if (PyTuple_Check(v)) {
  696.                 fv[i] = 1;
  697.                 if (!(argv[i] = Merge(v)))
  698.                     goto finally;
  699.                 fvc++;
  700.             }
  701.             else if (v == Py_None) {
  702.                 argc = i;
  703.                 break;
  704.             }
  705.             else {
  706.                 fv[i] = 0;
  707.                 if (!(argv[i] = AsString(v, tmp)))
  708.                     goto finally;
  709.                 fvc++;
  710.             }
  711.         }
  712.     }
  713.     /* End code copied from Merge() */
  714.  
  715.     /* All this to avoid a call to Tcl_Merge() and the corresponding call
  716.        to Tcl_SplitList() inside Tcl_Eval()...  It can save a bundle! */
  717.     if (Py_VerboseFlag >= 2) {
  718.         for (i = 0; i < argc; i++)
  719.             PySys_WriteStderr("%s ", argv[i]);
  720.     }
  721.     ENTER_TCL
  722.     info.proc = NULL;
  723.     if (argc < 1 ||
  724.         !Tcl_GetCommandInfo(interp, argv[0], &info) ||
  725.         info.proc == NULL)
  726.     {
  727.         char *cmd;
  728.         cmd = Tcl_Merge(argc, argv);
  729.         i = Tcl_Eval(interp, cmd);
  730.         ckfree(cmd);
  731.     }
  732.     else {
  733.         Tcl_ResetResult(interp);
  734.         i = (*info.proc)(info.clientData, interp, argc, argv);
  735.     }
  736.     ENTER_OVERLAP
  737.     if (info.proc == NULL && Py_VerboseFlag >= 2)
  738.         PySys_WriteStderr("... use TclEval ");
  739.     if (i == TCL_ERROR) {
  740.         if (Py_VerboseFlag >= 2)
  741.             PySys_WriteStderr("... error: '%s'\n",
  742.                 Tcl_GetStringResult(interp));
  743.         Tkinter_Error(self);
  744.     }
  745.     else {
  746.         if (Py_VerboseFlag >= 2)
  747.             PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp));
  748.         res = PyString_FromString(Tcl_GetStringResult(interp));
  749.     }
  750.     LEAVE_OVERLAP_TCL
  751.  
  752.     /* Copied from Merge() again */
  753.   finally:
  754.     for (i = 0; i < fvc; i++)
  755.         if (fv[i]) {
  756.             ckfree(argv[i]);
  757.         }
  758.     if (argv != argvStore)
  759.         ckfree(FREECAST argv);
  760.     if (fv != fvStore)
  761.         ckfree(FREECAST fv);
  762.  
  763.     Py_DECREF(tmp);
  764.     return res;
  765. }
  766.  
  767. #endif /* !USING_OBJECTS */
  768.  
  769. static PyObject *
  770. Tkapp_GlobalCall(PyObject *self, PyObject *args)
  771. {
  772.     /* Could do the same here as for Tkapp_Call(), but this is not used
  773.        much, so I can't be bothered.  Unfortunately Tcl doesn't export a
  774.        way for the user to do what all its Global* variants do (save and
  775.        reset the scope pointer, call the local version, restore the saved
  776.        scope pointer). */
  777.  
  778.     char *cmd;
  779.     PyObject *res = NULL;
  780.  
  781.     cmd  = Merge(args);
  782.     if (cmd) {
  783.         int err;
  784.         ENTER_TCL
  785.         err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
  786.         ENTER_OVERLAP
  787.         if (err == TCL_ERROR)
  788.             res = Tkinter_Error(self);
  789.         else
  790.             res = PyString_FromString(Tkapp_Result(self));
  791.         LEAVE_OVERLAP_TCL
  792.         ckfree(cmd);
  793.     }
  794.  
  795.     return res;
  796. }
  797.  
  798. static PyObject *
  799. Tkapp_Eval(PyObject *self, PyObject *args)
  800. {
  801.     char *script;
  802.     PyObject *res = NULL;
  803.     int err;
  804.   
  805.     if (!PyArg_ParseTuple(args, "s:eval", &script))
  806.         return NULL;
  807.  
  808.     ENTER_TCL
  809.     err = Tcl_Eval(Tkapp_Interp(self), script);
  810.     ENTER_OVERLAP
  811.     if (err == TCL_ERROR)
  812.         res = Tkinter_Error(self);
  813.     else
  814.         res = PyString_FromString(Tkapp_Result(self));
  815.     LEAVE_OVERLAP_TCL
  816.     return res;
  817. }
  818.  
  819. static PyObject *
  820. Tkapp_GlobalEval(PyObject *self, PyObject *args)
  821. {
  822.     char *script;
  823.     PyObject *res = NULL;
  824.     int err;
  825.  
  826.     if (!PyArg_ParseTuple(args, "s:globaleval", &script))
  827.         return NULL;
  828.  
  829.     ENTER_TCL
  830.     err = Tcl_GlobalEval(Tkapp_Interp(self), script);
  831.     ENTER_OVERLAP
  832.     if (err == TCL_ERROR)
  833.         res = Tkinter_Error(self);
  834.     else
  835.         res = PyString_FromString(Tkapp_Result(self));
  836.     LEAVE_OVERLAP_TCL
  837.     return res;
  838. }
  839.  
  840. static PyObject *
  841. Tkapp_EvalFile(PyObject *self, PyObject *args)
  842. {
  843.     char *fileName;
  844.     PyObject *res = NULL;
  845.     int err;
  846.  
  847.     if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
  848.         return NULL;
  849.  
  850.     ENTER_TCL
  851.     err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
  852.     ENTER_OVERLAP
  853.     if (err == TCL_ERROR)
  854.         res = Tkinter_Error(self);
  855.  
  856.     else
  857.         res = PyString_FromString(Tkapp_Result(self));
  858.     LEAVE_OVERLAP_TCL
  859.     return res;
  860. }
  861.  
  862. static PyObject *
  863. Tkapp_Record(PyObject *self, PyObject *args)
  864. {
  865.     char *script;
  866.     PyObject *res = NULL;
  867.     int err;
  868.  
  869.     if (!PyArg_ParseTuple(args, "s", &script))
  870.         return NULL;
  871.  
  872.     ENTER_TCL
  873.     err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
  874.     ENTER_OVERLAP
  875.     if (err == TCL_ERROR)
  876.         res = Tkinter_Error(self);
  877.     else
  878.         res = PyString_FromString(Tkapp_Result(self));
  879.     LEAVE_OVERLAP_TCL
  880.     return res;
  881. }
  882.  
  883. static PyObject *
  884. Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
  885. {
  886.     char *msg;
  887.  
  888.     if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
  889.         return NULL;
  890.     ENTER_TCL
  891.     Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
  892.     LEAVE_TCL
  893.  
  894.     Py_INCREF(Py_None);
  895.     return Py_None;
  896. }
  897.  
  898.  
  899.  
  900. /** Tcl Variable **/
  901.  
  902. static PyObject *
  903. SetVar(PyObject *self, PyObject *args, int flags)
  904. {
  905.     char *name1, *name2, *ok, *s;
  906.     PyObject *newValue;
  907.     PyObject *tmp;
  908.  
  909.     tmp = PyList_New(0);
  910.     if (!tmp)
  911.         return NULL;
  912.  
  913.     if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
  914.         /* XXX Merge? */
  915.         s = AsString(newValue, tmp);
  916.         if (s == NULL)
  917.             return NULL;
  918.         ENTER_TCL
  919.         ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
  920.         LEAVE_TCL
  921.     }
  922.     else {
  923.         PyErr_Clear();
  924.         if (PyArg_ParseTuple(args, "ssO:setvar",
  925.                      &name1, &name2, &newValue)) {
  926.             s = AsString(newValue, tmp);
  927.             if (s == NULL)
  928.                 return NULL;
  929.             ENTER_TCL
  930.             ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2, 
  931.                      s, flags);
  932.             LEAVE_TCL
  933.         }
  934.         else {
  935.             Py_DECREF(tmp);
  936.             return NULL;
  937.         }
  938.     }
  939.     Py_DECREF(tmp);
  940.  
  941.     if (!ok)
  942.         return Tkinter_Error(self);
  943.  
  944.     Py_INCREF(Py_None);
  945.     return Py_None;
  946. }
  947.  
  948. static PyObject *
  949. Tkapp_SetVar(PyObject *self, PyObject *args)
  950. {
  951.     return SetVar(self, args, TCL_LEAVE_ERR_MSG);
  952. }
  953.  
  954. static PyObject *
  955. Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
  956. {
  957.     return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  958. }
  959.  
  960.  
  961.  
  962. static PyObject *
  963. GetVar(PyObject *self, PyObject *args, int flags)
  964. {
  965.     char *name1, *name2=NULL, *s;
  966.     PyObject *res = NULL;
  967.  
  968.     if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
  969.         return NULL;
  970.     ENTER_TCL
  971.     if (name2 == NULL)
  972.         s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
  973.  
  974.     else
  975.         s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
  976.     ENTER_OVERLAP
  977.  
  978.     if (s == NULL)
  979.         res = Tkinter_Error(self);
  980.     else
  981.         res = PyString_FromString(s);
  982.     LEAVE_OVERLAP_TCL
  983.     return res;
  984. }
  985.  
  986. static PyObject *
  987. Tkapp_GetVar(PyObject *self, PyObject *args)
  988. {
  989.     return GetVar(self, args, TCL_LEAVE_ERR_MSG);
  990. }
  991.  
  992. static PyObject *
  993. Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
  994. {
  995.     return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  996. }
  997.  
  998.  
  999.  
  1000. static PyObject *
  1001. UnsetVar(PyObject *self, PyObject *args, int flags)
  1002. {
  1003.     char *name1, *name2=NULL;
  1004.     PyObject *res = NULL;
  1005.     int code;
  1006.  
  1007.     if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
  1008.         return NULL;
  1009.     ENTER_TCL
  1010.     if (name2 == NULL)
  1011.         code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
  1012.  
  1013.     else
  1014.         code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
  1015.     ENTER_OVERLAP
  1016.  
  1017.     if (code == TCL_ERROR)
  1018.         res = Tkinter_Error(self);
  1019.     else {
  1020.         Py_INCREF(Py_None);
  1021.         res = Py_None;
  1022.     }
  1023.     LEAVE_OVERLAP_TCL
  1024.     return res;
  1025. }
  1026.  
  1027. static PyObject *
  1028. Tkapp_UnsetVar(PyObject *self, PyObject *args)
  1029. {
  1030.     return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
  1031. }
  1032.  
  1033. static PyObject *
  1034. Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
  1035. {
  1036.     return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  1037. }
  1038.  
  1039.  
  1040.  
  1041. /** Tcl to Python **/
  1042.  
  1043. static PyObject *
  1044. Tkapp_GetInt(PyObject *self, PyObject *args)
  1045. {
  1046.     char *s;
  1047.     int v;
  1048.  
  1049.     if (!PyArg_ParseTuple(args, "s:getint", &s))
  1050.         return NULL;
  1051.     if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
  1052.         return Tkinter_Error(self);
  1053.     return Py_BuildValue("i", v);
  1054. }
  1055.  
  1056. static PyObject *
  1057. Tkapp_GetDouble(PyObject *self, PyObject *args)
  1058. {
  1059.     char *s;
  1060.     double v;
  1061.  
  1062.     if (!PyArg_ParseTuple(args, "s:getdouble", &s))
  1063.         return NULL;
  1064.     if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
  1065.         return Tkinter_Error(self);
  1066.     return Py_BuildValue("d", v);
  1067. }
  1068.  
  1069. static PyObject *
  1070. Tkapp_GetBoolean(PyObject *self, PyObject *args)
  1071. {
  1072.     char *s;
  1073.     int v;
  1074.  
  1075.     if (!PyArg_ParseTuple(args, "s:getboolean", &s))
  1076.         return NULL;
  1077.     if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
  1078.         return Tkinter_Error(self);
  1079.     return Py_BuildValue("i", v);
  1080. }
  1081.  
  1082. static PyObject *
  1083. Tkapp_ExprString(PyObject *self, PyObject *args)
  1084. {
  1085.     char *s;
  1086.     PyObject *res = NULL;
  1087.     int retval;
  1088.  
  1089.     if (!PyArg_ParseTuple(args, "s:exprstring", &s))
  1090.         return NULL;
  1091.     ENTER_TCL
  1092.     retval = Tcl_ExprString(Tkapp_Interp(self), s);
  1093.     ENTER_OVERLAP
  1094.     if (retval == TCL_ERROR)
  1095.         res = Tkinter_Error(self);
  1096.     else
  1097.         res = Py_BuildValue("s", Tkapp_Result(self));
  1098.     LEAVE_OVERLAP_TCL
  1099.     return res;
  1100. }
  1101.  
  1102. static PyObject *
  1103. Tkapp_ExprLong(PyObject *self, PyObject *args)
  1104. {
  1105.     char *s;
  1106.     PyObject *res = NULL;
  1107.     int retval;
  1108.     long v;
  1109.  
  1110.     if (!PyArg_ParseTuple(args, "s:exprlong", &s))
  1111.         return NULL;
  1112.     ENTER_TCL
  1113.     retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
  1114.     ENTER_OVERLAP
  1115.     if (retval == TCL_ERROR)
  1116.         res = Tkinter_Error(self);
  1117.     else
  1118.         res = Py_BuildValue("l", v);
  1119.     LEAVE_OVERLAP_TCL
  1120.     return res;
  1121. }
  1122.  
  1123. static PyObject *
  1124. Tkapp_ExprDouble(PyObject *self, PyObject *args)
  1125. {
  1126.     char *s;
  1127.     PyObject *res = NULL;
  1128.     double v;
  1129.     int retval;
  1130.  
  1131.     if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
  1132.         return NULL;
  1133.     PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
  1134.     ENTER_TCL
  1135.     retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
  1136.     ENTER_OVERLAP
  1137.     PyFPE_END_PROTECT(retval)
  1138.     if (retval == TCL_ERROR)
  1139.         res = Tkinter_Error(self);
  1140.     else
  1141.         res = Py_BuildValue("d", v);
  1142.     LEAVE_OVERLAP_TCL
  1143.     return res;
  1144. }
  1145.  
  1146. static PyObject *
  1147. Tkapp_ExprBoolean(PyObject *self, PyObject *args)
  1148. {
  1149.     char *s;
  1150.     PyObject *res = NULL;
  1151.     int retval;
  1152.     int v;
  1153.  
  1154.     if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
  1155.         return NULL;
  1156.     ENTER_TCL
  1157.     retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
  1158.     ENTER_OVERLAP
  1159.     if (retval == TCL_ERROR)
  1160.         res = Tkinter_Error(self);
  1161.     else
  1162.         res = Py_BuildValue("i", v);
  1163.     LEAVE_OVERLAP_TCL
  1164.     return res;
  1165. }
  1166.  
  1167.  
  1168.  
  1169. static PyObject *
  1170. Tkapp_SplitList(PyObject *self, PyObject *args)
  1171. {
  1172.     char *list;
  1173.     int argc;
  1174.     char **argv;
  1175.     PyObject *v;
  1176.     int i;
  1177.  
  1178.     if (!PyArg_ParseTuple(args, "s:splitlist", &list))
  1179.         return NULL;
  1180.  
  1181.     if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
  1182.         return Tkinter_Error(self);
  1183.  
  1184.     if (!(v = PyTuple_New(argc)))
  1185.         return NULL;
  1186.     
  1187.     for (i = 0; i < argc; i++) {
  1188.         PyObject *s = PyString_FromString(argv[i]);
  1189.         if (!s || PyTuple_SetItem(v, i, s)) {
  1190.             Py_DECREF(v);
  1191.             v = NULL;
  1192.             goto finally;
  1193.         }
  1194.     }
  1195.  
  1196.   finally:
  1197.     ckfree(FREECAST argv);
  1198.     return v;
  1199. }
  1200.  
  1201. static PyObject *
  1202. Tkapp_Split(PyObject *self, PyObject *args)
  1203. {
  1204.     char *list;
  1205.  
  1206.     if (!PyArg_ParseTuple(args, "s:split", &list))
  1207.         return NULL;
  1208.     return Split(list);
  1209. }
  1210.  
  1211. static PyObject *
  1212. Tkapp_Merge(PyObject *self, PyObject *args)
  1213. {
  1214.     char *s = Merge(args);
  1215.     PyObject *res = NULL;
  1216.  
  1217.     if (s) {
  1218.         res = PyString_FromString(s);
  1219.         ckfree(s);
  1220.     }
  1221.  
  1222.     return res;
  1223. }
  1224.  
  1225.  
  1226.  
  1227. /** Tcl Command **/
  1228.  
  1229. /* Client data struct */
  1230. typedef struct {
  1231.     PyObject *self;
  1232.     PyObject *func;
  1233. } PythonCmd_ClientData;
  1234.  
  1235. static int
  1236. PythonCmd_Error(Tcl_Interp *interp)
  1237. {
  1238.     errorInCmd = 1;
  1239.     PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
  1240.     LEAVE_PYTHON
  1241.     return TCL_ERROR;
  1242. }
  1243.  
  1244. /* This is the Tcl command that acts as a wrapper for Python
  1245.  * function or method.
  1246.  */
  1247. static int
  1248. PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
  1249. {
  1250.     PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
  1251.     PyObject *self, *func, *arg, *res, *tmp;
  1252.     int i, rv;
  1253.     char *s;
  1254.  
  1255.     ENTER_PYTHON
  1256.  
  1257.     /* TBD: no error checking here since we know, via the
  1258.      * Tkapp_CreateCommand() that the client data is a two-tuple
  1259.      */
  1260.     self = data->self;
  1261.     func = data->func;
  1262.  
  1263.     /* Create argument list (argv1, ..., argvN) */
  1264.     if (!(arg = PyTuple_New(argc - 1)))
  1265.         return PythonCmd_Error(interp);
  1266.  
  1267.     for (i = 0; i < (argc - 1); i++) {
  1268.         PyObject *s = PyString_FromString(argv[i + 1]);
  1269.         if (!s || PyTuple_SetItem(arg, i, s)) {
  1270.             Py_DECREF(arg);
  1271.             return PythonCmd_Error(interp);
  1272.         }
  1273.     }
  1274.     res = PyEval_CallObject(func, arg);
  1275.     Py_DECREF(arg);
  1276.  
  1277.     if (res == NULL)
  1278.         return PythonCmd_Error(interp);
  1279.  
  1280.     if (!(tmp = PyList_New(0))) {
  1281.         Py_DECREF(res);
  1282.         return PythonCmd_Error(interp);
  1283.     }
  1284.  
  1285.     s = AsString(res, tmp);
  1286.     if (s == NULL) {
  1287.         rv = PythonCmd_Error(interp);
  1288.     }
  1289.     else {
  1290.         Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
  1291.         rv = TCL_OK;
  1292.     }
  1293.  
  1294.     Py_DECREF(res);
  1295.     Py_DECREF(tmp);
  1296.  
  1297.     LEAVE_PYTHON
  1298.  
  1299.     return rv;
  1300. }
  1301.  
  1302. static void
  1303. PythonCmdDelete(ClientData clientData)
  1304. {
  1305.     PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
  1306.  
  1307.     ENTER_PYTHON
  1308.     Py_XDECREF(data->self);
  1309.     Py_XDECREF(data->func);
  1310.     PyMem_DEL(data);
  1311.     LEAVE_PYTHON
  1312. }
  1313.  
  1314.  
  1315.  
  1316. static PyObject *
  1317. Tkapp_CreateCommand(PyObject *self, PyObject *args)
  1318. {
  1319.     PythonCmd_ClientData *data;
  1320.     char *cmdName;
  1321.     PyObject *func;
  1322.     Tcl_Command err;
  1323.  
  1324.     if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
  1325.         return NULL;
  1326.     if (!PyCallable_Check(func)) {
  1327.         PyErr_SetString(PyExc_TypeError, "command not callable");
  1328.         return NULL;
  1329.     }
  1330.  
  1331.     data = PyMem_NEW(PythonCmd_ClientData, 1);
  1332.     if (!data)
  1333.         return NULL;
  1334.     Py_XINCREF(self);
  1335.     Py_XINCREF(func);
  1336.     data->self = self;
  1337.     data->func = func;
  1338.  
  1339.     ENTER_TCL
  1340.     err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
  1341.                 (ClientData)data, PythonCmdDelete);
  1342.     LEAVE_TCL
  1343.     if (err == NULL) {
  1344.         PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
  1345.         PyMem_DEL(data);
  1346.         return NULL;
  1347.     }
  1348.  
  1349.     Py_INCREF(Py_None);
  1350.     return Py_None;
  1351. }
  1352.  
  1353.  
  1354.  
  1355. static PyObject *
  1356. Tkapp_DeleteCommand(PyObject *self, PyObject *args)
  1357. {
  1358.     char *cmdName;
  1359.     int err;
  1360.  
  1361.     if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
  1362.         return NULL;
  1363.     ENTER_TCL
  1364.     err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
  1365.     LEAVE_TCL
  1366.     if (err == -1) {
  1367.         PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
  1368.         return NULL;
  1369.     }
  1370.     Py_INCREF(Py_None);
  1371.     return Py_None;
  1372. }
  1373.  
  1374.  
  1375.  
  1376. #ifdef HAVE_CREATEFILEHANDLER
  1377. /** File Handler **/
  1378.  
  1379. typedef struct _fhcdata {
  1380.     PyObject *func;
  1381.     PyObject *file;
  1382.     int id;
  1383.     struct _fhcdata *next;
  1384. } FileHandler_ClientData;
  1385.  
  1386. static FileHandler_ClientData *HeadFHCD;
  1387.  
  1388. static FileHandler_ClientData *
  1389. NewFHCD(PyObject *func, PyObject *file, int id)
  1390. {
  1391.     FileHandler_ClientData *p;
  1392.     p = PyMem_NEW(FileHandler_ClientData, 1);
  1393.     if (p != NULL) {
  1394.         Py_XINCREF(func);
  1395.         Py_XINCREF(file);
  1396.         p->func = func;
  1397.         p->file = file;
  1398.         p->id = id;
  1399.         p->next = HeadFHCD;
  1400.         HeadFHCD = p;
  1401.     }
  1402.     return p;
  1403. }
  1404.  
  1405. static void
  1406. DeleteFHCD(int id)
  1407. {
  1408.     FileHandler_ClientData *p, **pp;
  1409.     
  1410.     pp = &HeadFHCD; 
  1411.     while ((p = *pp) != NULL) {
  1412.         if (p->id == id) {
  1413.             *pp = p->next;
  1414.             Py_XDECREF(p->func);
  1415.             Py_XDECREF(p->file);
  1416.             PyMem_DEL(p);
  1417.         }
  1418.         else
  1419.             pp = &p->next;
  1420.     }
  1421. }
  1422.  
  1423. static void
  1424. FileHandler(ClientData clientData, int mask)
  1425. {
  1426.     FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
  1427.     PyObject *func, *file, *arg, *res;
  1428.  
  1429.     ENTER_PYTHON
  1430.     func = data->func;
  1431.     file = data->file;
  1432.  
  1433.     arg = Py_BuildValue("(Oi)", file, (long) mask);
  1434.     res = PyEval_CallObject(func, arg);
  1435.     Py_DECREF(arg);
  1436.  
  1437.     if (res == NULL) {
  1438.         errorInCmd = 1;
  1439.         PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
  1440.     }
  1441.     Py_XDECREF(res);
  1442.     LEAVE_PYTHON
  1443. }
  1444.  
  1445. static PyObject *
  1446. Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
  1447.      /* args is (file, mask, func) */
  1448. {
  1449.     FileHandler_ClientData *data;
  1450.     PyObject *file, *func;
  1451.     int mask, tfile;
  1452.  
  1453.     if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
  1454.                   &file, &mask, &func))
  1455.         return NULL;
  1456.     tfile = PyObject_AsFileDescriptor(file);
  1457.     if (tfile < 0)
  1458.         return NULL;
  1459.     if (!PyCallable_Check(func)) {
  1460.         PyErr_SetString(PyExc_TypeError, "bad argument list");
  1461.         return NULL;
  1462.     }
  1463.  
  1464.     data = NewFHCD(func, file, tfile);
  1465.     if (data == NULL)
  1466.         return NULL;
  1467.  
  1468.     /* Ought to check for null Tcl_File object... */
  1469.     ENTER_TCL
  1470.     Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
  1471.     LEAVE_TCL
  1472.     Py_INCREF(Py_None);
  1473.     return Py_None;
  1474. }
  1475.  
  1476. static PyObject *
  1477. Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
  1478. {
  1479.     PyObject *file;
  1480.     int tfile;
  1481.   
  1482.     if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
  1483.         return NULL;
  1484.     tfile = PyObject_AsFileDescriptor(file);
  1485.     if (tfile < 0)
  1486.         return NULL;
  1487.  
  1488.     DeleteFHCD(tfile);
  1489.  
  1490.     /* Ought to check for null Tcl_File object... */
  1491.     ENTER_TCL
  1492.     Tcl_DeleteFileHandler(tfile);
  1493.     LEAVE_TCL
  1494.     Py_INCREF(Py_None);
  1495.     return Py_None;
  1496. }
  1497. #endif /* HAVE_CREATEFILEHANDLER */
  1498.  
  1499.  
  1500. /**** Tktt Object (timer token) ****/
  1501.  
  1502. staticforward PyTypeObject Tktt_Type;
  1503.  
  1504. typedef struct {
  1505.     PyObject_HEAD
  1506.     Tcl_TimerToken token;
  1507.     PyObject *func;
  1508. } TkttObject;
  1509.  
  1510. static PyObject *
  1511. Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
  1512. {
  1513.     TkttObject *v = (TkttObject *)self;
  1514.     PyObject *func = v->func;
  1515.  
  1516.     if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
  1517.         return NULL;
  1518.     if (v->token != NULL) {
  1519.         Tcl_DeleteTimerHandler(v->token);
  1520.         v->token = NULL;
  1521.     }
  1522.     if (func != NULL) {
  1523.         v->func = NULL;
  1524.         Py_DECREF(func);
  1525.         Py_DECREF(v); /* See Tktt_New() */
  1526.     }
  1527.     Py_INCREF(Py_None);
  1528.     return Py_None;
  1529. }
  1530.  
  1531. static PyMethodDef Tktt_methods[] =
  1532. {
  1533.     {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
  1534.     {NULL, NULL}
  1535. };
  1536.  
  1537. static TkttObject *
  1538. Tktt_New(PyObject *func)
  1539. {
  1540.     TkttObject *v;
  1541.   
  1542.     v = PyObject_New(TkttObject, &Tktt_Type);
  1543.     if (v == NULL)
  1544.         return NULL;
  1545.  
  1546.     Py_INCREF(func);
  1547.     v->token = NULL;
  1548.     v->func = func;
  1549.  
  1550.     /* Extra reference, deleted when called or when handler is deleted */
  1551.     Py_INCREF(v);
  1552.     return v;
  1553. }
  1554.  
  1555. static void
  1556. Tktt_Dealloc(PyObject *self)
  1557. {
  1558.     TkttObject *v = (TkttObject *)self;
  1559.     PyObject *func = v->func;
  1560.  
  1561.     Py_XDECREF(func);
  1562.  
  1563.     PyObject_Del(self);
  1564. }
  1565.  
  1566. static PyObject *
  1567. Tktt_Repr(PyObject *self)
  1568. {
  1569.     TkttObject *v = (TkttObject *)self;
  1570.     char buf[100];
  1571.  
  1572.     sprintf(buf, "<tktimertoken at %p%s>", v,
  1573.         v->func == NULL ? ", handler deleted" : "");
  1574.     return PyString_FromString(buf);
  1575. }
  1576.  
  1577. static PyObject *
  1578. Tktt_GetAttr(PyObject *self, char *name)
  1579. {
  1580.     return Py_FindMethod(Tktt_methods, self, name);
  1581. }
  1582.  
  1583. static PyTypeObject Tktt_Type =
  1584. {
  1585.     PyObject_HEAD_INIT(NULL)
  1586.     0,                     /*ob_size */
  1587.     "tktimertoken",                 /*tp_name */
  1588.     sizeof(TkttObject),             /*tp_basicsize */
  1589.     0,                     /*tp_itemsize */
  1590.     Tktt_Dealloc,                 /*tp_dealloc */
  1591.     0,                     /*tp_print */
  1592.     Tktt_GetAttr,                 /*tp_getattr */
  1593.     0,                     /*tp_setattr */
  1594.     0,                     /*tp_compare */
  1595.     Tktt_Repr,                 /*tp_repr */
  1596.     0,                     /*tp_as_number */
  1597.     0,                     /*tp_as_sequence */
  1598.     0,                     /*tp_as_mapping */
  1599.     0,                     /*tp_hash */
  1600. };
  1601.  
  1602.  
  1603.  
  1604. /** Timer Handler **/
  1605.  
  1606. static void
  1607. TimerHandler(ClientData clientData)
  1608. {
  1609.     TkttObject *v = (TkttObject *)clientData;
  1610.     PyObject *func = v->func;
  1611.     PyObject *res;
  1612.  
  1613.     if (func == NULL)
  1614.         return;
  1615.  
  1616.     v->func = NULL;
  1617.  
  1618.     ENTER_PYTHON
  1619.  
  1620.     res  = PyEval_CallObject(func, NULL);
  1621.     Py_DECREF(func);
  1622.     Py_DECREF(v); /* See Tktt_New() */
  1623.  
  1624.     if (res == NULL) {
  1625.         errorInCmd = 1;
  1626.         PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
  1627.     }
  1628.     else
  1629.         Py_DECREF(res);
  1630.  
  1631.     LEAVE_PYTHON
  1632. }
  1633.  
  1634. static PyObject *
  1635. Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
  1636. {
  1637.     int milliseconds;
  1638.     PyObject *func;
  1639.     TkttObject *v;
  1640.  
  1641.     if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
  1642.                   &milliseconds, &func))
  1643.         return NULL;
  1644.     if (!PyCallable_Check(func)) {
  1645.         PyErr_SetString(PyExc_TypeError, "bad argument list");
  1646.         return NULL;
  1647.     }
  1648.     v = Tktt_New(func);
  1649.     v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
  1650.                       (ClientData)v);
  1651.  
  1652.     return (PyObject *) v;
  1653. }
  1654.  
  1655.  
  1656. /** Event Loop **/
  1657.  
  1658. static PyObject *
  1659. Tkapp_MainLoop(PyObject *self, PyObject *args)
  1660. {
  1661.     int threshold = 0;
  1662. #ifdef WITH_THREAD
  1663.     PyThreadState *tstate = PyThreadState_Get();
  1664. #endif
  1665.  
  1666.     if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
  1667.         return NULL;
  1668.  
  1669.     quitMainLoop = 0;
  1670.     while (Tk_GetNumMainWindows() > threshold &&
  1671.            !quitMainLoop &&
  1672.            !errorInCmd)
  1673.     {
  1674.         int result;
  1675.  
  1676. #ifdef WITH_THREAD
  1677.         Py_BEGIN_ALLOW_THREADS
  1678.         PyThread_acquire_lock(tcl_lock, 1);
  1679.         tcl_tstate = tstate;
  1680.         result = Tcl_DoOneEvent(TCL_DONT_WAIT);
  1681.         tcl_tstate = NULL;
  1682.         PyThread_release_lock(tcl_lock);
  1683.         if (result == 0)
  1684.             Sleep(20);
  1685.         Py_END_ALLOW_THREADS
  1686. #else
  1687.         result = Tcl_DoOneEvent(0);
  1688. #endif
  1689.  
  1690.         if (PyErr_CheckSignals() != 0)
  1691.             return NULL;
  1692.         if (result < 0)
  1693.             break;
  1694.     }
  1695.     quitMainLoop = 0;
  1696.  
  1697.     if (errorInCmd) {
  1698.         errorInCmd = 0;
  1699.         PyErr_Restore(excInCmd, valInCmd, trbInCmd);
  1700.         excInCmd = valInCmd = trbInCmd = NULL;
  1701.         return NULL;
  1702.     }
  1703.     Py_INCREF(Py_None);
  1704.     return Py_None;
  1705. }
  1706.  
  1707. static PyObject *
  1708. Tkapp_DoOneEvent(PyObject *self, PyObject *args)
  1709. {
  1710.     int flags = 0;
  1711.     int rv;
  1712.  
  1713.     if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
  1714.         return NULL;
  1715.  
  1716.     ENTER_TCL
  1717.     rv = Tcl_DoOneEvent(flags);
  1718.     LEAVE_TCL
  1719.     return Py_BuildValue("i", rv);
  1720. }
  1721.  
  1722. static PyObject *
  1723. Tkapp_Quit(PyObject *self, PyObject *args)
  1724. {
  1725.  
  1726.     if (!PyArg_ParseTuple(args, ":quit"))
  1727.         return NULL;
  1728.  
  1729.     quitMainLoop = 1;
  1730.     Py_INCREF(Py_None);
  1731.     return Py_None;
  1732. }
  1733.  
  1734. static PyObject *
  1735. Tkapp_InterpAddr(PyObject *self, PyObject *args)
  1736. {
  1737.  
  1738.     if (!PyArg_ParseTuple(args, ":interpaddr"))
  1739.         return NULL;
  1740.  
  1741.     return PyInt_FromLong((long)Tkapp_Interp(self));
  1742. }
  1743.  
  1744.  
  1745.  
  1746. /**** Tkapp Method List ****/
  1747.  
  1748. static PyMethodDef Tkapp_methods[] =
  1749. {
  1750.     {"call",            Tkapp_Call, 0},
  1751.     {"globalcall",            Tkapp_GlobalCall, 0},
  1752.     {"eval",            Tkapp_Eval, 1},
  1753.     {"globaleval",            Tkapp_GlobalEval, 1},
  1754.     {"evalfile",            Tkapp_EvalFile, 1},
  1755.     {"record",            Tkapp_Record, 1},
  1756.     {"adderrorinfo",       Tkapp_AddErrorInfo, 1},
  1757.     {"setvar",            Tkapp_SetVar, 1},
  1758.     {"globalsetvar",       Tkapp_GlobalSetVar, 1},
  1759.     {"getvar",            Tkapp_GetVar, 1},
  1760.     {"globalgetvar",       Tkapp_GlobalGetVar, 1},
  1761.     {"unsetvar",            Tkapp_UnsetVar, 1},
  1762.     {"globalunsetvar",     Tkapp_GlobalUnsetVar, 1},
  1763.     {"getint",            Tkapp_GetInt, 1},
  1764.     {"getdouble",            Tkapp_GetDouble, 1},
  1765.     {"getboolean",            Tkapp_GetBoolean, 1},
  1766.     {"exprstring",            Tkapp_ExprString, 1},
  1767.     {"exprlong",            Tkapp_ExprLong, 1},
  1768.     {"exprdouble",            Tkapp_ExprDouble, 1},
  1769.     {"exprboolean",        Tkapp_ExprBoolean, 1},
  1770.     {"splitlist",            Tkapp_SplitList, 1},
  1771.     {"split",            Tkapp_Split, 1},
  1772.     {"merge",            Tkapp_Merge, 0},
  1773.     {"createcommand",      Tkapp_CreateCommand, 1},
  1774.     {"deletecommand",      Tkapp_DeleteCommand, 1},
  1775. #ifdef HAVE_CREATEFILEHANDLER
  1776.     {"createfilehandler",  Tkapp_CreateFileHandler, 1},
  1777.     {"deletefilehandler",  Tkapp_DeleteFileHandler, 1},
  1778. #endif
  1779.     {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
  1780.     {"mainloop",            Tkapp_MainLoop, 1},
  1781.     {"dooneevent",            Tkapp_DoOneEvent, 1},
  1782.     {"quit",            Tkapp_Quit, 1},
  1783.     {"interpaddr",         Tkapp_InterpAddr, 1},
  1784.     {NULL,                NULL}
  1785. };
  1786.  
  1787.  
  1788.  
  1789. /**** Tkapp Type Methods ****/
  1790.  
  1791. static void
  1792. Tkapp_Dealloc(PyObject *self)
  1793. {
  1794.     ENTER_TCL
  1795.     Tcl_DeleteInterp(Tkapp_Interp(self));
  1796.     LEAVE_TCL
  1797.     PyObject_Del(self);
  1798.     DisableEventHook();
  1799. }
  1800.  
  1801. static PyObject *
  1802. Tkapp_GetAttr(PyObject *self, char *name)
  1803. {
  1804.     return Py_FindMethod(Tkapp_methods, self, name);
  1805. }
  1806.  
  1807. static PyTypeObject Tkapp_Type =
  1808. {
  1809.     PyObject_HEAD_INIT(NULL)
  1810.     0,                     /*ob_size */
  1811.     "tkapp",                 /*tp_name */
  1812.     sizeof(TkappObject),             /*tp_basicsize */
  1813.     0,                     /*tp_itemsize */
  1814.     Tkapp_Dealloc,                 /*tp_dealloc */
  1815.     0,                     /*tp_print */
  1816.     Tkapp_GetAttr,                 /*tp_getattr */
  1817.     0,                     /*tp_setattr */
  1818.     0,                     /*tp_compare */
  1819.     0,                     /*tp_repr */
  1820.     0,                     /*tp_as_number */
  1821.     0,                     /*tp_as_sequence */
  1822.     0,                     /*tp_as_mapping */
  1823.     0,                     /*tp_hash */
  1824. };
  1825.  
  1826.  
  1827.  
  1828. /**** Tkinter Module ****/
  1829.  
  1830. typedef struct {
  1831.     PyObject* tuple;
  1832.     int size; /* current size */
  1833.     int maxsize; /* allocated size */
  1834. } FlattenContext;
  1835.  
  1836. static int
  1837. _bump(FlattenContext* context, int size)
  1838. {
  1839.     /* expand tuple to hold (at least) size new items.
  1840.        return true if successful, false if an exception was raised */
  1841.  
  1842.     int maxsize = context->maxsize * 2;
  1843.  
  1844.     if (maxsize < context->size + size)
  1845.         maxsize = context->size + size;
  1846.  
  1847.     context->maxsize = maxsize;
  1848.  
  1849.     return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
  1850. }
  1851.  
  1852. static int
  1853. _flatten1(FlattenContext* context, PyObject* item, int depth)
  1854. {
  1855.     /* add tuple or list to argument tuple (recursively) */
  1856.  
  1857.     int i, size;
  1858.  
  1859.     if (depth > 1000) {
  1860.         PyErr_SetString(PyExc_ValueError,
  1861.                 "nesting too deep in _flatten");
  1862.         return 0;
  1863.     } else if (PyList_Check(item)) {
  1864.         size = PyList_GET_SIZE(item);
  1865.         /* preallocate (assume no nesting) */
  1866.         if (context->size + size > context->maxsize &&
  1867.             !_bump(context, size))
  1868.             return 0;
  1869.         /* copy items to output tuple */
  1870.         for (i = 0; i < size; i++) {
  1871.             PyObject *o = PyList_GET_ITEM(item, i);
  1872.             if (PyList_Check(o) || PyTuple_Check(o)) {
  1873.                 if (!_flatten1(context, o, depth + 1))
  1874.                     return 0;
  1875.             } else if (o != Py_None) {
  1876.                 if (context->size + 1 > context->maxsize &&
  1877.                     !_bump(context, 1))
  1878.                     return 0;
  1879.                 Py_INCREF(o);
  1880.                 PyTuple_SET_ITEM(context->tuple,
  1881.                          context->size++, o);
  1882.             }
  1883.         }
  1884.     } else if (PyTuple_Check(item)) {
  1885.         /* same, for tuples */
  1886.         size = PyTuple_GET_SIZE(item);
  1887.         if (context->size + size > context->maxsize &&
  1888.             !_bump(context, size))
  1889.             return 0;
  1890.         for (i = 0; i < size; i++) {
  1891.             PyObject *o = PyTuple_GET_ITEM(item, i);
  1892.             if (PyList_Check(o) || PyTuple_Check(o)) {
  1893.                 if (!_flatten1(context, o, depth + 1))
  1894.                     return 0;
  1895.             } else if (o != Py_None) {
  1896.                 if (context->size + 1 > context->maxsize &&
  1897.                     !_bump(context, 1))
  1898.                     return 0;
  1899.                 Py_INCREF(o);
  1900.                 PyTuple_SET_ITEM(context->tuple,
  1901.                          context->size++, o);
  1902.             }
  1903.         }
  1904.     } else {
  1905.         PyErr_SetString(PyExc_TypeError, "argument must be sequence");
  1906.         return 0;
  1907.     }
  1908.     return 1;
  1909. }
  1910.  
  1911. static PyObject *
  1912. Tkinter_Flatten(PyObject* self, PyObject* args)
  1913. {
  1914.     FlattenContext context;
  1915.     PyObject* item;
  1916.  
  1917.     if (!PyArg_ParseTuple(args, "O:_flatten", &item))
  1918.         return NULL;
  1919.  
  1920.     context.maxsize = PySequence_Size(item);
  1921.     if (context.maxsize <= 0)
  1922.         return PyTuple_New(0);
  1923.     
  1924.     context.tuple = PyTuple_New(context.maxsize);
  1925.     if (!context.tuple)
  1926.         return NULL;
  1927.     
  1928.     context.size = 0;
  1929.  
  1930.     if (!_flatten1(&context, item,0))
  1931.         return NULL;
  1932.  
  1933.     if (_PyTuple_Resize(&context.tuple, context.size, 0))
  1934.         return NULL;
  1935.  
  1936.     return context.tuple;
  1937. }
  1938.  
  1939. static PyObject *
  1940. Tkinter_Create(PyObject *self, PyObject *args)
  1941. {
  1942.     char *screenName = NULL;
  1943.     char *baseName = NULL;
  1944.     char *className = NULL;
  1945.     int interactive = 0;
  1946.  
  1947.     baseName = strrchr(Py_GetProgramName(), '/');
  1948.     if (baseName != NULL)
  1949.         baseName++;
  1950.     else
  1951.         baseName = Py_GetProgramName();
  1952.     className = "Tk";
  1953.   
  1954.     if (!PyArg_ParseTuple(args, "|zssi:create",
  1955.                   &screenName, &baseName, &className,
  1956.                   &interactive))
  1957.         return NULL;
  1958.  
  1959.     return (PyObject *) Tkapp_New(screenName, baseName, className, 
  1960.                       interactive);
  1961. }
  1962.  
  1963. static PyMethodDef moduleMethods[] =
  1964. {
  1965.     {"_flatten",           Tkinter_Flatten, 1},
  1966.     {"create",             Tkinter_Create, 1},
  1967. #ifdef HAVE_CREATEFILEHANDLER
  1968.     {"createfilehandler",  Tkapp_CreateFileHandler, 1},
  1969.     {"deletefilehandler",  Tkapp_DeleteFileHandler, 1},
  1970. #endif
  1971.     {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
  1972.     {"mainloop",           Tkapp_MainLoop, 1},
  1973.     {"dooneevent",         Tkapp_DoOneEvent, 1},
  1974.     {"quit",               Tkapp_Quit, 1},
  1975.     {NULL,                 NULL}
  1976. };
  1977.  
  1978. #ifdef WAIT_FOR_STDIN
  1979.  
  1980. static int stdin_ready = 0;
  1981.  
  1982. #ifndef MS_WINDOWS
  1983. static void
  1984. MyFileProc(void *clientData, int mask)
  1985. {
  1986.     stdin_ready = 1;
  1987. }
  1988. #endif
  1989.  
  1990. static PyThreadState *event_tstate = NULL;
  1991.  
  1992. static int
  1993. EventHook(void)
  1994. {
  1995. #ifndef MS_WINDOWS
  1996.     int tfile;
  1997. #endif
  1998. #ifdef WITH_THREAD
  1999.     PyEval_RestoreThread(event_tstate);
  2000. #endif
  2001.     stdin_ready = 0;
  2002.     errorInCmd = 0;
  2003. #ifndef MS_WINDOWS
  2004.     tfile = fileno(stdin);
  2005.     Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
  2006. #endif
  2007.     while (!errorInCmd && !stdin_ready) {
  2008.         int result;
  2009. #ifdef MS_WINDOWS
  2010.         if (_kbhit()) {
  2011.             stdin_ready = 1;
  2012.             break;
  2013.         }
  2014. #endif
  2015. #if defined(WITH_THREAD) || defined(MS_WINDOWS)
  2016.         Py_BEGIN_ALLOW_THREADS
  2017.         PyThread_acquire_lock(tcl_lock, 1);
  2018.         tcl_tstate = event_tstate;
  2019.  
  2020.         result = Tcl_DoOneEvent(TCL_DONT_WAIT);
  2021.  
  2022.         tcl_tstate = NULL;
  2023.         PyThread_release_lock(tcl_lock);
  2024.         if (result == 0)
  2025.             Sleep(20);
  2026.         Py_END_ALLOW_THREADS
  2027. #else
  2028.         result = Tcl_DoOneEvent(0);
  2029. #endif
  2030.  
  2031.         if (result < 0)
  2032.             break;
  2033.     }
  2034. #ifndef MS_WINDOWS
  2035.     Tcl_DeleteFileHandler(tfile);
  2036. #endif
  2037.     if (errorInCmd) {
  2038.         errorInCmd = 0;
  2039.         PyErr_Restore(excInCmd, valInCmd, trbInCmd);
  2040.         excInCmd = valInCmd = trbInCmd = NULL;
  2041.         PyErr_Print();
  2042.     }
  2043. #ifdef WITH_THREAD
  2044.     PyEval_SaveThread();
  2045. #endif
  2046.     return 0;
  2047. }
  2048.  
  2049. #endif
  2050.  
  2051. static void
  2052. EnableEventHook(void)
  2053. {
  2054. #ifdef WAIT_FOR_STDIN
  2055.     if (PyOS_InputHook == NULL) {
  2056. #ifdef WITH_THREAD
  2057.         event_tstate = PyThreadState_Get();
  2058. #endif
  2059.         PyOS_InputHook = EventHook;
  2060.     }
  2061. #endif
  2062. }
  2063.  
  2064. static void
  2065. DisableEventHook(void)
  2066. {
  2067. #ifdef WAIT_FOR_STDIN
  2068.     if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
  2069.         PyOS_InputHook = NULL;
  2070.     }
  2071. #endif
  2072. }
  2073.  
  2074.  
  2075. /* all errors will be checked in one fell swoop in init_tkinter() */
  2076. static void
  2077. ins_long(PyObject *d, char *name, long val)
  2078. {
  2079.     PyObject *v = PyInt_FromLong(val);
  2080.     if (v) {
  2081.         PyDict_SetItemString(d, name, v);
  2082.         Py_DECREF(v);
  2083.     }
  2084. }
  2085. static void
  2086. ins_string(PyObject *d, char *name, char *val)
  2087. {
  2088.     PyObject *v = PyString_FromString(val);
  2089.     if (v) {
  2090.         PyDict_SetItemString(d, name, v);
  2091.         Py_DECREF(v);
  2092.     }
  2093. }
  2094.  
  2095.  
  2096. DL_EXPORT(void)
  2097. init_tkinter(void)
  2098. {
  2099.     PyObject *m, *d;
  2100.  
  2101.     Tkapp_Type.ob_type = &PyType_Type;
  2102.  
  2103. #ifdef WITH_THREAD
  2104.     tcl_lock = PyThread_allocate_lock();
  2105. #endif
  2106.  
  2107.     m = Py_InitModule("_tkinter", moduleMethods);
  2108.  
  2109.     d = PyModule_GetDict(m);
  2110.     Tkinter_TclError = Py_BuildValue("s", "TclError");
  2111.     PyDict_SetItemString(d, "TclError", Tkinter_TclError);
  2112.  
  2113.     ins_long(d, "READABLE", TCL_READABLE);
  2114.     ins_long(d, "WRITABLE", TCL_WRITABLE);
  2115.     ins_long(d, "EXCEPTION", TCL_EXCEPTION);
  2116.     ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
  2117.     ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
  2118.     ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
  2119.     ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
  2120.     ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
  2121.     ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
  2122.     ins_string(d, "TK_VERSION", TK_VERSION);
  2123.     ins_string(d, "TCL_VERSION", TCL_VERSION);
  2124.  
  2125.     PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
  2126.  
  2127.     Tktt_Type.ob_type = &PyType_Type;
  2128.     PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
  2129.  
  2130.     /* This helps the dynamic loader; in Unicode aware Tcl versions
  2131.        it also helps Tcl find its encodings. */
  2132.     Tcl_FindExecutable(Py_GetProgramName());
  2133.  
  2134.     if (PyErr_Occurred())
  2135.         return;
  2136.  
  2137. #if 0
  2138.     /* This was not a good idea; through <Destroy> bindings,
  2139.        Tcl_Finalize() may invoke Python code but at that point the
  2140.        interpreter and thread state have already been destroyed! */
  2141.     Py_AtExit(Tcl_Finalize);
  2142. #endif
  2143.  
  2144. #ifdef macintosh
  2145.     /*
  2146.     ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
  2147.     ** Most of the initializations in that routine (toolbox init calls and
  2148.     ** such) have already been done for us, so we only need these.
  2149.     */
  2150.     tcl_macQdPtr = &qd;
  2151.  
  2152.     Tcl_MacSetEventProc(PyMacConvertEvent);
  2153. #if GENERATINGCFM
  2154.     mac_addlibresources();
  2155. #endif /* GENERATINGCFM */
  2156. #endif /* macintosh */
  2157. }
  2158.  
  2159.  
  2160.  
  2161. #ifdef macintosh
  2162.  
  2163. /*
  2164. ** Anyone who embeds Tcl/Tk on the Mac must define panic().
  2165. */
  2166.  
  2167. void
  2168. panic(char * format, ...)
  2169. {
  2170.     va_list varg;
  2171.     
  2172.     va_start(varg, format);
  2173.     
  2174.     vfprintf(stderr, format, varg);
  2175.     (void) fflush(stderr);
  2176.     
  2177.     va_end(varg);
  2178.  
  2179.     Py_FatalError("Tcl/Tk panic");
  2180. }
  2181.  
  2182. /*
  2183. ** Pass events to SIOUX before passing them to Tk.
  2184. */
  2185.  
  2186. static int
  2187. PyMacConvertEvent(EventRecord *eventPtr)
  2188. {
  2189.     WindowPtr frontwin;
  2190.     /*
  2191.     ** Sioux eats too many events, so we don't pass it everything.  We
  2192.     ** always pass update events to Sioux, and we only pass other events if
  2193.     ** the Sioux window is frontmost. This means that Tk menus don't work
  2194.     ** in that case, but at least we can scroll the sioux window.
  2195.     ** Note that the SIOUXIsAppWindow() routine we use here is not really
  2196.     ** part of the external interface of Sioux...
  2197.     */
  2198.     frontwin = FrontWindow();
  2199.     if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
  2200.         if (SIOUXHandleOneEvent(eventPtr))
  2201.             return 0; /* Nothing happened to the Tcl event queue */
  2202.     }
  2203.     return TkMacConvertEvent(eventPtr);
  2204. }
  2205.  
  2206. #if GENERATINGCFM
  2207.  
  2208. /*
  2209. ** Additional Mac specific code for dealing with shared libraries.
  2210. */
  2211.  
  2212. #include <Resources.h>
  2213. #include <CodeFragments.h>
  2214.  
  2215. static int loaded_from_shlib = 0;
  2216. static FSSpec library_fss;
  2217.  
  2218. /*
  2219. ** If this module is dynamically loaded the following routine should
  2220. ** be the init routine. It takes care of adding the shared library to
  2221. ** the resource-file chain, so that the tk routines can find their
  2222. ** resources.
  2223. */
  2224. OSErr pascal
  2225. init_tkinter_shlib(CFragInitBlockPtr data)
  2226. {
  2227.     __initialize();
  2228.     if ( data == nil ) return noErr;
  2229.     if ( data->fragLocator.where == kDataForkCFragLocator ) {
  2230.         library_fss = *data->fragLocator.u.onDisk.fileSpec;
  2231.         loaded_from_shlib = 1;
  2232.     } else if ( data->fragLocator.where == kResourceCFragLocator ) {
  2233.         library_fss = *data->fragLocator.u.inSegs.fileSpec;
  2234.         loaded_from_shlib = 1;
  2235.     }
  2236.     return noErr;
  2237. }
  2238.  
  2239. /*
  2240. ** Insert the library resources into the search path. Put them after
  2241. ** the resources from the application. Again, we ignore errors.
  2242. */
  2243. static
  2244. mac_addlibresources(void)
  2245. {
  2246.     if ( !loaded_from_shlib ) 
  2247.         return;
  2248.     (void)FSpOpenResFile(&library_fss, fsRdPerm);
  2249. }
  2250.  
  2251. #endif /* GENERATINGCFM */
  2252. #endif /* macintosh */
  2253.