home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Modules / stdwinmodule.c < prev    next >
C/C++ Source or Header  |  2000-12-21  |  55KB  |  2,665 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI or Corporation for National Research Initiatives or
  13. CNRI not be used in advertising or publicity pertaining to
  14. distribution of the software without specific, written prior
  15. permission.
  16.  
  17. While CWI is the initial source for this software, a modified version
  18. is made available by the Corporation for National Research Initiatives
  19. (CNRI) at the Internet address ftp://ftp.python.org.
  20.  
  21. STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
  22. REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  23. MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
  24. CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  25. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  27. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  28. PERFORMANCE OF THIS SOFTWARE.
  29.  
  30. ******************************************************************/
  31.  
  32. /* Stdwin module */
  33.  
  34. /* Stdwin itself is a module, not a separate object type.
  35.    Object types defined here:
  36.     wp: a window
  37.     dp: a drawing structure (only one can exist at a time)
  38.     mp: a menu
  39.     tp: a textedit block
  40.     bp: a bitmap
  41. */
  42.  
  43. /* Rules for translating C stdwin function calls into Python stwin:
  44.    - All names drop their initial letter 'w'
  45.    - Functions with a window as first parameter are methods of window objects
  46.    - There is no equivalent for wclose(); just delete the window object
  47.      (all references to it!)  (XXX maybe this is a bad idea)
  48.    - w.begindrawing() returns a drawing object
  49.    - There is no equivalent for wenddrawing(win); just delete the drawing
  50.       object (all references to it!)  (XXX maybe this is a bad idea)
  51.    - Functions that may only be used inside wbegindrawing / wendddrawing
  52.      are methods of the drawing object; this includes the text measurement
  53.      functions (which however have doubles as module functions).
  54.    - Methods of the drawing object drop an initial 'draw' from their name
  55.      if they have it, e.g., wdrawline() --> d.line()
  56.    - The obvious type conversions: int --> intobject; string --> stringobject
  57.    - A text parameter followed by a length parameter is only a text (string)
  58.      parameter in Python
  59.    - A point or other pair of horizontal and vertical coordinates is always
  60.      a pair of integers in Python
  61.    - Two points forming a rectangle or endpoints of a line segment are a
  62.      pair of points in Python
  63.    - The arguments to d.elarc() are three points.
  64.    - The functions wgetclip() and wsetclip() are translated into
  65.      stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
  66.      a bad word for what these functions do (clipping has a different
  67.      meaning in the drawing world), while cutbuffer is standard X jargon.
  68.      XXX This must change again in the light of changes to stdwin!
  69.    - For textedit, similar rules hold, but they are less strict.
  70.    XXX more?
  71. */
  72.  
  73. #include "Python.h"
  74.  
  75. #ifdef macintosh
  76. #include "macglue.h"
  77. #endif
  78.  
  79. #ifdef macintosh
  80. #include ":::stdwin:H:stdwin.h"
  81. #else /* !macintosh */
  82. #include "stdwin.h"
  83. #define HAVE_BITMAPS
  84. #endif /* !macintosh */
  85.  
  86. #ifdef WITH_THREAD
  87.  
  88. #include "pythread.h"
  89.  
  90. static PyThread_type_lock StdwinLock; /* Lock held when interpreter not locked */
  91.  
  92. #define BGN_STDWIN Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(StdwinLock, 1);
  93. #define RET_STDWIN PyThread_release_lock(StdwinLock); Py_BLOCK_THREADS
  94. #define END_STDWIN PyThread_release_lock(StdwinLock); Py_END_ALLOW_THREADS
  95.  
  96. #else
  97.  
  98. #define BGN_STDWIN Py_BEGIN_ALLOW_THREADS
  99. #define RET_STDWIN Py_BLOCK_THREADS
  100. #define END_STDWIN Py_END_ALLOW_THREADS
  101.  
  102. #endif
  103.  
  104. #define getintarg(v,a) PyArg_Parse(v, "i", a)
  105. #define getlongarg(v,a) PyArg_Parse(v, "l", a)
  106. #define getstrarg(v,a) PyArg_Parse(v, "s", a)
  107. #define getpointarg(v, a) PyArg_Parse(v, "(ii)", a, (a)+1)
  108. #define get3pointarg(v, a) PyArg_Parse(v, "((ii)(ii)(ii))", \
  109.                                        a, a+1, a+2, a+3, a+4, a+5)
  110. #define getrectarg(v, a) PyArg_Parse(v, "((ii)(ii))", a, a+1, a+2, a+3)
  111. #define getrectintarg(v, a) PyArg_Parse(v, "(((ii)(ii))i)", \
  112.                                         a, a+1, a+2, a+3, a+4)
  113. #define getpointintarg(v, a) PyArg_Parse(v, "((ii)i)", a, a+1, a+2)
  114. #define getrectpointarg(v, a) PyArg_Parse(v, "(((ii)(ii))(ii))", \
  115.                                           a, a+1, a+2, a+3, a+4, a+5)
  116.  
  117. static PyObject *StdwinError; /* Exception stdwin.error */
  118.  
  119. /* Window and menu object types declared here because of forward references */
  120.  
  121. typedef struct {
  122.     PyObject_HEAD
  123.     PyObject    *w_title;
  124.     WINDOW      *w_win;
  125.     PyObject    *w_attr;             /* Attributes dictionary */
  126. } windowobject;
  127.  
  128. staticforward PyTypeObject Windowtype;
  129.  
  130. #define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
  131.  
  132. typedef struct {
  133.     PyObject_HEAD
  134.     MENU        *m_menu;
  135.     int          m_id;
  136.     PyObject    *m_attr;             /* Attributes dictionary */
  137. } menuobject;
  138.  
  139. staticforward PyTypeObject Menutype;
  140.  
  141. #define is_menuobject(mp) ((mp)->ob_type == &Menutype)
  142.  
  143. typedef struct {
  144.     PyObject_HEAD
  145.     BITMAP      *b_bitmap;
  146.     PyObject    *b_attr;             /* Attributes dictionary */
  147. } bitmapobject;
  148.  
  149. staticforward PyTypeObject Bitmaptype;
  150.  
  151. #define is_bitmapobject(mp) ((mp)->ob_type == &Bitmaptype)
  152.  
  153.  
  154. /* Strongly stdwin-specific argument handlers */
  155.  
  156. static int
  157. getmenudetail(v, ep)
  158.     PyObject *v;
  159.     EVENT *ep;
  160. {
  161.     menuobject *mp;
  162.     if (!PyArg_Parse(v, "(Oi)", &mp, &ep->u.m.item))
  163.         return 0;
  164.     if (!is_menuobject(mp))
  165.         return PyErr_BadArgument();
  166.     ep->u.m.id = mp->m_id;
  167.     return 1;
  168. }
  169.  
  170. static int
  171. geteventarg(v, ep)
  172.     PyObject *v;
  173.     EVENT *ep;
  174. {
  175.     PyObject *wp, *detail;
  176.     int a[4];
  177.     if (!PyArg_Parse(v, "(iOO)", &ep->type, &wp, &detail))
  178.         return 0;
  179.     if (is_windowobject(wp))
  180.         ep->window = ((windowobject *)wp) -> w_win;
  181.     else if (wp == Py_None)
  182.         ep->window = NULL;
  183.     else
  184.         return PyErr_BadArgument();
  185.     switch (ep->type) {
  186.     case WE_CHAR: {
  187.             char c;
  188.             if (!PyArg_Parse(detail, "c", &c))
  189.                 return 0;
  190.             ep->u.character = c;
  191.             return 1;
  192.         }
  193.     case WE_COMMAND:
  194.         return getintarg(detail, &ep->u.command);
  195.     case WE_DRAW:
  196.         if (!getrectarg(detail, a))
  197.             return 0;
  198.         ep->u.area.left = a[0];
  199.         ep->u.area.top = a[1];
  200.         ep->u.area.right = a[2];
  201.         ep->u.area.bottom = a[3];
  202.         return 1;
  203.     case WE_MOUSE_DOWN:
  204.     case WE_MOUSE_UP:
  205.     case WE_MOUSE_MOVE:
  206.         return PyArg_Parse(detail, "((ii)iii)",
  207.                                    &ep->u.where.h, &ep->u.where.v,
  208.                                    &ep->u.where.clicks,
  209.                                    &ep->u.where.button,
  210.                                    &ep->u.where.mask);
  211.     case WE_MENU:
  212.         return getmenudetail(detail, ep);
  213.     case WE_KEY:
  214.         return PyArg_Parse(detail, "(ii)",
  215.                                    &ep->u.key.code, &ep->u.key.mask);
  216.     default:
  217.         return 1;
  218.     }
  219. }
  220.  
  221.  
  222. /* Return construction tools */
  223.  
  224. static PyObject *
  225. makepoint(a, b)
  226.     int a, b;
  227. {
  228.     return Py_BuildValue("(ii)", a, b);
  229. }
  230.  
  231. static PyObject *
  232. makerect(a, b, c, d)
  233.     int a, b, c, d;
  234. {
  235.     return Py_BuildValue("((ii)(ii))", a, b, c, d);
  236. }
  237.  
  238.  
  239. /* Drawing objects */
  240.  
  241. typedef struct {
  242.     PyObject_HEAD
  243.     windowobject    *d_ref;
  244. } drawingobject;
  245.  
  246. static drawingobject *Drawing; /* Set to current drawing object, or NULL */
  247.  
  248. /* Drawing methods */
  249.  
  250. static PyObject *
  251. drawing_close(dp)
  252.     drawingobject *dp;
  253. {
  254.     if (dp->d_ref != NULL) {
  255.         wenddrawing(dp->d_ref->w_win);
  256.         Drawing = NULL;
  257.         Py_DECREF(dp->d_ref);
  258.         dp->d_ref = NULL;
  259.     }
  260.     Py_INCREF(Py_None);
  261.     return Py_None;
  262. }
  263.  
  264. static void
  265. drawing_dealloc(dp)
  266.     drawingobject *dp;
  267. {
  268.     if (dp->d_ref != NULL) {
  269.         wenddrawing(dp->d_ref->w_win);
  270.         Drawing = NULL;
  271.         Py_DECREF(dp->d_ref);
  272.         dp->d_ref = NULL;
  273.     }
  274.     free((char *)dp);
  275. }
  276.  
  277. static PyObject *
  278. drawing_generic(dp, args, func)
  279.     drawingobject *dp;
  280.     PyObject *args;
  281.     void (*func) Py_FPROTO((int, int, int, int));
  282. {
  283.     int a[4];
  284.     if (!getrectarg(args, a))
  285.         return NULL;
  286.     (*func)(a[0], a[1], a[2], a[3]);
  287.     Py_INCREF(Py_None);
  288.     return Py_None;
  289. }
  290.  
  291. static PyObject *
  292. drawing_line(dp, args)
  293.     drawingobject *dp;
  294.     PyObject *args;
  295. {
  296.     return drawing_generic(dp, args, wdrawline);
  297. }
  298.  
  299. static PyObject *
  300. drawing_xorline(dp, args)
  301.     drawingobject *dp;
  302.     PyObject *args;
  303. {
  304.     return drawing_generic(dp, args, wxorline);
  305. }
  306.  
  307. static PyObject *
  308. drawing_circle(dp, args)
  309.     drawingobject *dp;
  310.     PyObject *args;
  311. {
  312.     int a[3];
  313.     if (!getpointintarg(args, a))
  314.         return NULL;
  315.     wdrawcircle(a[0], a[1], a[2]);
  316.     Py_INCREF(Py_None);
  317.     return Py_None;
  318. }
  319.  
  320. static PyObject *
  321. drawing_fillcircle(dp, args)
  322.     drawingobject *dp;
  323.     PyObject *args;
  324. {
  325.     int a[3];
  326.     if (!getpointintarg(args, a))
  327.         return NULL;
  328.     wfillcircle(a[0], a[1], a[2]);
  329.     Py_INCREF(Py_None);
  330.     return Py_None;
  331. }
  332.  
  333. static PyObject *
  334. drawing_xorcircle(dp, args)
  335.     drawingobject *dp;
  336.     PyObject *args;
  337. {
  338.     int a[3];
  339.     if (!getpointintarg(args, a))
  340.         return NULL;
  341.     wxorcircle(a[0], a[1], a[2]);
  342.     Py_INCREF(Py_None);
  343.     return Py_None;
  344. }
  345.  
  346. static PyObject *
  347. drawing_elarc(dp, args)
  348.     drawingobject *dp;
  349.     PyObject *args;
  350. {
  351.     int a[6];
  352.     if (!get3pointarg(args, a))
  353.         return NULL;
  354.     wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
  355.     Py_INCREF(Py_None);
  356.     return Py_None;
  357. }
  358.  
  359. static PyObject *
  360. drawing_fillelarc(dp, args)
  361.     drawingobject *dp;
  362.     PyObject *args;
  363. {
  364.     int a[6];
  365.     if (!get3pointarg(args, a))
  366.         return NULL;
  367.     wfillelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
  368.     Py_INCREF(Py_None);
  369.     return Py_None;
  370. }
  371.  
  372. static PyObject *
  373. drawing_xorelarc(dp, args)
  374.     drawingobject *dp;
  375.     PyObject *args;
  376. {
  377.     int a[6];
  378.     if (!get3pointarg(args, a))
  379.         return NULL;
  380.     wxorelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
  381.     Py_INCREF(Py_None);
  382.     return Py_None;
  383. }
  384.  
  385. static PyObject *
  386. drawing_box(dp, args)
  387.     drawingobject *dp;
  388.     PyObject *args;
  389. {
  390.     return drawing_generic(dp, args, wdrawbox);
  391. }
  392.  
  393. static PyObject *
  394. drawing_erase(dp, args)
  395.     drawingobject *dp;
  396.     PyObject *args;
  397. {
  398.     return drawing_generic(dp, args, werase);
  399. }
  400.  
  401. static PyObject *
  402. drawing_paint(dp, args)
  403.     drawingobject *dp;
  404.     PyObject *args;
  405. {
  406.     return drawing_generic(dp, args, wpaint);
  407. }
  408.  
  409. static PyObject *
  410. drawing_invert(dp, args)
  411.     drawingobject *dp;
  412.     PyObject *args;
  413. {
  414.     return drawing_generic(dp, args, winvert);
  415. }
  416.  
  417. static POINT *
  418. getpointsarray(v, psize)
  419.     PyObject *v;
  420.     int *psize;
  421. {
  422.     int n = -1;
  423.     PyObject * (*getitem) Py_PROTO((PyObject *, int));
  424.     int i;
  425.     POINT *points;
  426.  
  427.     if (v == NULL)
  428.         ;
  429.     else if (PyList_Check(v)) {
  430.         n = PyList_Size(v);
  431.         getitem = PyList_GetItem;
  432.     }
  433.     else if (PyTuple_Check(v)) {
  434.         n = PyTuple_Size(v);
  435.         getitem = PyTuple_GetItem;
  436.     }
  437.  
  438.     if (n <= 0) {
  439.         (void) PyErr_BadArgument();
  440.         return NULL;
  441.     }
  442.  
  443.     points = PyMem_NEW(POINT, n);
  444.     if (points == NULL) {
  445.         (void) PyErr_NoMemory();
  446.         return NULL;
  447.     }
  448.  
  449.     for (i = 0; i < n; i++) {
  450.         PyObject *w = (*getitem)(v, i);
  451.         int a[2];
  452.         if (!getpointarg(w, a)) {
  453.             PyMem_DEL(points);
  454.             return NULL;
  455.         }
  456.         points[i].h = a[0];
  457.         points[i].v = a[1];
  458.     }
  459.  
  460.     *psize = n;
  461.     return points;
  462. }
  463.  
  464. static PyObject *
  465. drawing_poly(dp, args)
  466.     drawingobject *dp;
  467.     PyObject *args;
  468. {
  469.     int n;
  470.     POINT *points = getpointsarray(args, &n);
  471.     if (points == NULL)
  472.         return NULL;
  473.     wdrawpoly(n, points);
  474.     PyMem_DEL(points);
  475.     Py_INCREF(Py_None);
  476.     return Py_None;
  477. }
  478.  
  479. static PyObject *
  480. drawing_fillpoly(dp, args)
  481.     drawingobject *dp;
  482.     PyObject *args;
  483. {
  484.     int n;
  485.     POINT *points = getpointsarray(args, &n);
  486.     if (points == NULL)
  487.         return NULL;
  488.     wfillpoly(n, points);
  489.     PyMem_DEL(points);
  490.     Py_INCREF(Py_None);
  491.     return Py_None;
  492. }
  493.  
  494. static PyObject *
  495. drawing_xorpoly(dp, args)
  496.     drawingobject *dp;
  497.     PyObject *args;
  498. {
  499.     int n;
  500.     POINT *points = getpointsarray(args, &n);
  501.     if (points == NULL)
  502.         return NULL;
  503.     wxorpoly(n, points);
  504.     PyMem_DEL(points);
  505.     Py_INCREF(Py_None);
  506.     return Py_None;
  507. }
  508.  
  509. static PyObject *
  510. drawing_cliprect(dp, args)
  511.     drawingobject *dp;
  512.     PyObject *args;
  513. {
  514.     return drawing_generic(dp, args, wcliprect);
  515. }
  516.  
  517. static PyObject *
  518. drawing_noclip(dp, args)
  519.     drawingobject *dp;
  520.     PyObject *args;
  521. {
  522.     if (!PyArg_NoArgs(args))
  523.         return NULL;
  524.     wnoclip();
  525.     Py_INCREF(Py_None);
  526.     return Py_None;
  527. }
  528.  
  529. static PyObject *
  530. drawing_shade(dp, args)
  531.     drawingobject *dp;
  532.     PyObject *args;
  533. {
  534.     int a[5];
  535.     if (!getrectintarg(args, a))
  536.         return NULL;
  537.     wshade(a[0], a[1], a[2], a[3], a[4]);
  538.     Py_INCREF(Py_None);
  539.     return Py_None;
  540. }
  541.  
  542. static PyObject *
  543. drawing_text(dp, args)
  544.     drawingobject *dp;
  545.     PyObject *args;
  546. {
  547.     int h, v, size;
  548.     char *text;
  549.     if (!PyArg_Parse(args, "((ii)t#)", &h, &v, &text, &size))
  550.         return NULL;
  551.     wdrawtext(h, v, text, size);
  552.     Py_INCREF(Py_None);
  553.     return Py_None;
  554. }
  555.  
  556. /* The following four are also used as stdwin functions */
  557.  
  558. static PyObject *
  559. drawing_lineheight(dp, args)
  560.     drawingobject *dp;
  561.     PyObject *args;
  562. {
  563.     if (!PyArg_NoArgs(args))
  564.         return NULL;
  565.     return PyInt_FromLong((long)wlineheight());
  566. }
  567.  
  568. static PyObject *
  569. drawing_baseline(dp, args)
  570.     drawingobject *dp;
  571.     PyObject *args;
  572. {
  573.     if (!PyArg_NoArgs(args))
  574.         return NULL;
  575.     return PyInt_FromLong((long)wbaseline());
  576. }
  577.  
  578. static PyObject *
  579. drawing_textwidth(dp, args)
  580.     drawingobject *dp;
  581.     PyObject *args;
  582. {
  583.     char *text;
  584.     int size;
  585.     if (!PyArg_Parse(args, "t#", &text, &size))
  586.         return NULL;
  587.     return PyInt_FromLong((long)wtextwidth(text, size));
  588. }
  589.  
  590. static PyObject *
  591. drawing_textbreak(dp, args)
  592.     drawingobject *dp;
  593.     PyObject *args;
  594. {
  595.     char *text;
  596.     int size, width;
  597.     if (!PyArg_Parse(args, "(t#i)", &text, &size, &width))
  598.         return NULL;
  599.     return PyInt_FromLong((long)wtextbreak(text, size, width));
  600. }
  601.  
  602. static PyObject *
  603. drawing_setfont(self, args)
  604.     drawingobject *self;
  605.     PyObject *args;
  606. {
  607.     char *font;
  608.     char style = '\0';
  609.     int size = 0;
  610.     if (args == NULL || !PyTuple_Check(args)) {
  611.         if (!PyArg_Parse(args, "z", &font))
  612.             return NULL;
  613.     }
  614.     else {
  615.         int n = PyTuple_Size(args);
  616.         if (n == 2) {
  617.             if (!PyArg_Parse(args, "(zi)", &font, &size))
  618.                 return NULL;
  619.         }
  620.         else if (!PyArg_Parse(args, "(zic)", &font, &size, &style)) {
  621.             PyErr_Clear();
  622.             if (!PyArg_Parse(args, "(zci)", &font, &style, &size))
  623.                 return NULL;
  624.         }
  625.     }
  626.     if (font != NULL) {
  627.         if (!wsetfont(font)) {
  628.             PyErr_SetString(StdwinError, "font not found");
  629.             return NULL;
  630.         }
  631.     }
  632.     if (size != 0)
  633.         wsetsize(size);
  634.     switch (style) {
  635.     case 'b':
  636.         wsetbold();
  637.         break;
  638.     case 'i':
  639.         wsetitalic();
  640.         break;
  641.     case 'o':
  642.         wsetbolditalic();
  643.         break;
  644.     case 'u':
  645.         wsetunderline();
  646.         break;
  647.     case 'p':
  648.         wsetplain();
  649.         break;
  650.     }
  651.     Py_INCREF(Py_None);
  652.     return Py_None;
  653. }
  654.  
  655. static PyObject *
  656. drawing_getbgcolor(self, args)
  657.     PyObject *self;
  658.     PyObject *args;
  659. {
  660.     if (!PyArg_NoArgs(args))
  661.         return NULL;
  662.     return PyInt_FromLong((long)wgetbgcolor());
  663. }
  664.  
  665. static PyObject *
  666. drawing_getfgcolor(self, args)
  667.     PyObject *self;
  668.     PyObject *args;
  669. {
  670.     if (!PyArg_NoArgs(args))
  671.         return NULL;
  672.     return PyInt_FromLong((long)wgetfgcolor());
  673. }
  674.  
  675. static PyObject *
  676. drawing_setbgcolor(self, args)
  677.     PyObject *self;
  678.     PyObject *args;
  679. {
  680.     long color;
  681.     if (!getlongarg(args, &color))
  682.         return NULL;
  683.     wsetbgcolor((COLOR)color);
  684.     Py_INCREF(Py_None);
  685.     return Py_None;
  686. }
  687.  
  688. static PyObject *
  689. drawing_setfgcolor(self, args)
  690.     PyObject *self;
  691.     PyObject *args;
  692. {
  693.     long color;
  694.     if (!getlongarg(args, &color))
  695.         return NULL;
  696.     wsetfgcolor((COLOR)color);
  697.     Py_INCREF(Py_None);
  698.     return Py_None;
  699. }
  700.  
  701. #ifdef HAVE_BITMAPS
  702.  
  703. static PyObject *
  704. drawing_bitmap(self, args)
  705.     PyObject *self;
  706.     PyObject *args;
  707. {
  708.     int h, v;
  709.     PyObject *bp;
  710.     PyObject *mask = NULL;
  711.     if (!PyArg_Parse(args, "((ii)O)", &h, &v, &bp)) {
  712.         PyErr_Clear();
  713.         if (!PyArg_Parse(args, "((ii)OO)", &h, &v, &bp, &mask))
  714.             return NULL;
  715.         if (mask == Py_None)
  716.             mask = NULL;
  717.         else if (!is_bitmapobject(mask)) {
  718.             PyErr_BadArgument();
  719.             return NULL;
  720.         }
  721.     }
  722.     if (!is_bitmapobject(bp)) {
  723.         PyErr_BadArgument();
  724.         return NULL;
  725.     }
  726.     if (((bitmapobject *)bp)->b_bitmap == NULL ||
  727.         mask != NULL && ((bitmapobject *)mask)->b_bitmap == NULL) {
  728.         PyErr_SetString(StdwinError, "bitmap object already close");
  729.         return NULL;
  730.     }
  731.     if (mask == NULL)
  732.         wdrawbitmap(h, v, ((bitmapobject *)bp)->b_bitmap, ALLBITS);
  733.     else
  734.         wdrawbitmap(h, v,
  735.                 ((bitmapobject *)bp)->b_bitmap,
  736.                 ((bitmapobject *)bp)->b_bitmap);
  737.     Py_INCREF(Py_None);
  738.     return Py_None;
  739. }
  740.  
  741. #endif /* HAVE_BITMAPS */
  742.  
  743. static PyMethodDef drawing_methods[] = {
  744. #ifdef HAVE_BITMAPS
  745.     {"bitmap",    (PyCFunction)drawing_bitmap},
  746. #endif
  747.     {"box",        (PyCFunction)drawing_box},
  748.     {"circle",    (PyCFunction)drawing_circle},
  749.     {"cliprect",    (PyCFunction)drawing_cliprect},
  750.     {"close",    (PyCFunction)drawing_close},
  751.     {"elarc",    (PyCFunction)drawing_elarc},
  752.     {"enddrawing",    (PyCFunction)drawing_close},
  753.     {"erase",    (PyCFunction)drawing_erase},
  754.     {"fillcircle",    (PyCFunction)drawing_fillcircle},
  755.     {"fillelarc",    (PyCFunction)drawing_fillelarc},
  756.     {"fillpoly",    (PyCFunction)drawing_fillpoly},
  757.     {"invert",    (PyCFunction)drawing_invert},
  758.     {"line",    (PyCFunction)drawing_line},
  759.     {"noclip",    (PyCFunction)drawing_noclip},
  760.     {"paint",    (PyCFunction)drawing_paint},
  761.     {"poly",    (PyCFunction)drawing_poly},
  762.     {"shade",    (PyCFunction)drawing_shade},
  763.     {"text",    (PyCFunction)drawing_text},
  764.     {"xorcircle",    (PyCFunction)drawing_xorcircle},
  765.     {"xorelarc",    (PyCFunction)drawing_xorelarc},
  766.     {"xorline",    (PyCFunction)drawing_xorline},
  767.     {"xorpoly",    (PyCFunction)drawing_xorpoly},
  768.     
  769.     /* Text measuring methods: */
  770.     {"baseline",    (PyCFunction)drawing_baseline},
  771.     {"lineheight",    (PyCFunction)drawing_lineheight},
  772.     {"textbreak",    (PyCFunction)drawing_textbreak},
  773.     {"textwidth",    (PyCFunction)drawing_textwidth},
  774.  
  775.     /* Font setting methods: */
  776.     {"setfont",    (PyCFunction)drawing_setfont},
  777.     
  778.     /* Color methods: */
  779.     {"getbgcolor",    (PyCFunction)drawing_getbgcolor},
  780.     {"getfgcolor",    (PyCFunction)drawing_getfgcolor},
  781.     {"setbgcolor",    (PyCFunction)drawing_setbgcolor},
  782.     {"setfgcolor",    (PyCFunction)drawing_setfgcolor},
  783.  
  784.     {NULL,        NULL}        /* sentinel */
  785. };
  786.  
  787. static PyObject *
  788. drawing_getattr(dp, name)
  789.     drawingobject *dp;
  790.     char *name;
  791. {
  792.     if (dp->d_ref == NULL) {
  793.         PyErr_SetString(StdwinError, "drawing object already closed");
  794.         return NULL;
  795.     }
  796.     return Py_FindMethod(drawing_methods, (PyObject *)dp, name);
  797. }
  798.  
  799. PyTypeObject Drawingtype = {
  800.     PyObject_HEAD_INIT(&PyType_Type)
  801.     0,            /*ob_size*/
  802.     "drawing",        /*tp_name*/
  803.     sizeof(drawingobject),    /*tp_size*/
  804.     0,            /*tp_itemsize*/
  805.     /* methods */
  806.     (destructor)drawing_dealloc, /*tp_dealloc*/
  807.     0,            /*tp_print*/
  808.     (getattrfunc)drawing_getattr, /*tp_getattr*/
  809.     0,            /*tp_setattr*/
  810.     0,            /*tp_compare*/
  811.     0,            /*tp_repr*/
  812. };
  813.  
  814.  
  815. /* Text(edit) objects */
  816.  
  817. typedef struct {
  818.     PyObject_HEAD
  819.     TEXTEDIT    *t_text;
  820.     windowobject    *t_ref;
  821.     PyObject    *t_attr;         /* Attributes dictionary */
  822. } textobject;
  823.  
  824. staticforward PyTypeObject Texttype;
  825.  
  826. static textobject *
  827. newtextobject(wp, left, top, right, bottom)
  828.     windowobject *wp;
  829.     int left, top, right, bottom;
  830. {
  831.     textobject *tp;
  832.     tp = PyObject_NEW(textobject, &Texttype);
  833.     if (tp == NULL)
  834.         return NULL;
  835.     tp->t_attr = NULL;
  836.     Py_INCREF(wp);
  837.     tp->t_ref = wp;
  838.     tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
  839.     if (tp->t_text == NULL) {
  840.         Py_DECREF(tp);
  841.         return (textobject *) PyErr_NoMemory();
  842.     }
  843.     return tp;
  844. }
  845.  
  846. /* Text(edit) methods */
  847.  
  848. static void
  849. text_dealloc(tp)
  850.     textobject *tp;
  851. {
  852.     if (tp->t_text != NULL)
  853.         tefree(tp->t_text);
  854.     Py_XDECREF(tp->t_attr);
  855.     Py_XDECREF(tp->t_ref);
  856.     PyMem_DEL(tp);
  857. }
  858.  
  859. static PyObject *
  860. text_close(tp, args)
  861.     textobject *tp;
  862.     PyObject *args;
  863. {
  864.     if (tp->t_text != NULL) {
  865.         tefree(tp->t_text);
  866.         tp->t_text = NULL;
  867.     }
  868.     if (tp->t_attr != NULL) {
  869.         Py_DECREF(tp->t_attr);
  870.         tp->t_attr = NULL;
  871.     }
  872.     if (tp->t_ref != NULL) {
  873.         Py_DECREF(tp->t_ref);
  874.         tp->t_ref = NULL;
  875.     }
  876.     Py_INCREF(Py_None);
  877.     return Py_None;
  878. }
  879.  
  880. static PyObject *
  881. text_arrow(self, args)
  882.     textobject *self;
  883.     PyObject *args;
  884. {
  885.     int code;
  886.     if (!getintarg(args, &code))
  887.         return NULL;
  888.     tearrow(self->t_text, code);
  889.     Py_INCREF(Py_None);
  890.     return Py_None;
  891. }
  892.  
  893. static PyObject *
  894. text_draw(self, args)
  895.     textobject *self;
  896.     PyObject *args;
  897. {
  898.     register TEXTEDIT *tp = self->t_text;
  899.     int a[4];
  900.     int left, top, right, bottom;
  901.     if (!getrectarg(args, a))
  902.         return NULL;
  903.     if (Drawing != NULL) {
  904.         PyErr_SetString(StdwinError, "already drawing");
  905.         return NULL;
  906.     }
  907.     /* Clip to text area and ignore if area is empty */
  908.     left = tegetleft(tp);
  909.     top = tegettop(tp);
  910.     right = tegetright(tp);
  911.     bottom = tegetbottom(tp);
  912.     if (a[0] < left) a[0] = left;
  913.     if (a[1] < top) a[1] = top;
  914.     if (a[2] > right) a[2] = right;
  915.     if (a[3] > bottom) a[3] = bottom;
  916.     if (a[0] < a[2] && a[1] < a[3]) {
  917.         wbegindrawing(self->t_ref->w_win);
  918.         tedrawnew(tp, a[0], a[1], a[2], a[3]);
  919.         wenddrawing(self->t_ref->w_win);
  920.     }
  921.     Py_INCREF(Py_None);
  922.     return Py_None;
  923. }
  924.  
  925. static PyObject *
  926. text_event(self, args)
  927.     textobject *self;
  928.     PyObject *args;
  929. {
  930.     register TEXTEDIT *tp = self->t_text;
  931.     EVENT e;
  932.     if (!geteventarg(args, &e))
  933.         return NULL;
  934.     if (e.type == WE_MOUSE_DOWN) {
  935.         /* Cheat at the margins */
  936.         int width, height;
  937.         wgetdocsize(e.window, &width, &height);
  938.         if (e.u.where.h < 0 && tegetleft(tp) == 0)
  939.             e.u.where.h = 0;
  940.         else if (e.u.where.h > width && tegetright(tp) == width)
  941.             e.u.where.h = width;
  942.         if (e.u.where.v < 0 && tegettop(tp) == 0)
  943.             e.u.where.v = 0;
  944.         else if (e.u.where.v > height && tegetright(tp) == height)
  945.             e.u.where.v = height;
  946.     }
  947.     return PyInt_FromLong((long) teevent(tp, &e));
  948. }
  949.  
  950. static PyObject *
  951. text_getfocus(self, args)
  952.     textobject *self;
  953.     PyObject *args;
  954. {
  955.     if (!PyArg_NoArgs(args))
  956.         return NULL;
  957.     return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
  958. }
  959.  
  960. static PyObject *
  961. text_getfocustext(self, args)
  962.     textobject *self;
  963.     PyObject *args;
  964. {
  965.     int f1, f2;
  966.     char *text;
  967.     if (!PyArg_NoArgs(args))
  968.         return NULL;
  969.     f1 = tegetfoc1(self->t_text);
  970.     f2 = tegetfoc2(self->t_text);
  971.     text = tegettext(self->t_text);
  972.     return PyString_FromStringAndSize(text + f1, f2-f1);
  973. }
  974.  
  975. static PyObject *
  976. text_getrect(self, args)
  977.     textobject *self;
  978.     PyObject *args;
  979. {
  980.     if (!PyArg_NoArgs(args))
  981.         return NULL;
  982.     return makerect(tegetleft(self->t_text),
  983.             tegettop(self->t_text),
  984.             tegetright(self->t_text),
  985.             tegetbottom(self->t_text));
  986. }
  987.  
  988. static PyObject *
  989. text_gettext(self, args)
  990.     textobject *self;
  991.     PyObject *args;
  992. {
  993.     if (!PyArg_NoArgs(args))
  994.         return NULL;
  995.     return PyString_FromStringAndSize(tegettext(self->t_text),
  996.                       tegetlen(self->t_text));
  997. }
  998.  
  999. static PyObject *
  1000. text_move(self, args)
  1001.     textobject *self;
  1002.     PyObject *args;
  1003. {
  1004.     int a[4];
  1005.     if (!getrectarg(args, a))
  1006.         return NULL;
  1007.     temovenew(self->t_text, a[0], a[1], a[2], a[3]);
  1008.     Py_INCREF(Py_None);
  1009.     return Py_None;
  1010. }
  1011.  
  1012. static PyObject *
  1013. text_replace(self, args)
  1014.     textobject *self;
  1015.     PyObject *args;
  1016. {
  1017.     char *text;
  1018.     if (!getstrarg(args, &text))
  1019.         return NULL;
  1020.     tereplace(self->t_text, text);
  1021.     Py_INCREF(Py_None);
  1022.     return Py_None;
  1023. }
  1024.  
  1025. static PyObject *
  1026. text_setactive(self, args)
  1027.     textobject *self;
  1028.     PyObject *args;
  1029. {
  1030.     int flag;
  1031.     if (!getintarg(args, &flag))
  1032.         return NULL;
  1033.     tesetactive(self->t_text, flag);
  1034.     Py_INCREF(Py_None);
  1035.     return Py_None;
  1036. }
  1037.  
  1038. static PyObject *
  1039. text_setfocus(self, args)
  1040.     textobject *self;
  1041.     PyObject *args;
  1042. {
  1043.     int a[2];
  1044.     if (!getpointarg(args, a))
  1045.         return NULL;
  1046.     tesetfocus(self->t_text, a[0], a[1]);
  1047.     Py_INCREF(Py_None);
  1048.     return Py_None;
  1049. }
  1050.  
  1051. static PyObject *
  1052. text_settext(self, args)
  1053.     textobject *self;
  1054.     PyObject *args;
  1055. {
  1056.     char *text;
  1057.     char *buf;
  1058.     int size;
  1059.     if (!PyArg_Parse(args, "t#", &text, &size))
  1060.         return NULL;
  1061.     if ((buf = PyMem_NEW(char, size)) == NULL) {
  1062.         return PyErr_NoMemory();
  1063.     }
  1064.     memcpy(buf, text, size);
  1065.     tesetbuf(self->t_text, buf, size); /* Becomes owner of buffer */
  1066.     Py_INCREF(Py_None);
  1067.     return Py_None;
  1068. }
  1069.  
  1070. static PyObject *
  1071. text_setview(self, args)
  1072.     textobject *self;
  1073.     PyObject *args;
  1074. {
  1075.     int a[4];
  1076.     if (args == Py_None)
  1077.         tenoview(self->t_text);
  1078.     else {
  1079.         if (!getrectarg(args, a))
  1080.             return NULL;
  1081.         tesetview(self->t_text, a[0], a[1], a[2], a[3]);
  1082.     }
  1083.     Py_INCREF(Py_None);
  1084.     return Py_None;
  1085. }
  1086.  
  1087. static PyMethodDef text_methods[] = {
  1088.     {"arrow",    (PyCFunction)text_arrow},
  1089.     {"close",    (PyCFunction)text_close},
  1090.     {"draw",    (PyCFunction)text_draw},
  1091.     {"event",    (PyCFunction)text_event},
  1092.     {"getfocus",    (PyCFunction)text_getfocus},
  1093.     {"getfocustext",(PyCFunction)text_getfocustext},
  1094.     {"getrect",    (PyCFunction)text_getrect},
  1095.     {"gettext",    (PyCFunction)text_gettext},
  1096.     {"move",    (PyCFunction)text_move},
  1097.     {"replace",    (PyCFunction)text_replace},
  1098.     {"setactive",    (PyCFunction)text_setactive},
  1099.     {"setfocus",    (PyCFunction)text_setfocus},
  1100.     {"settext",    (PyCFunction)text_settext},
  1101.     {"setview",    (PyCFunction)text_setview},
  1102.     {NULL,        NULL}        /* sentinel */
  1103. };
  1104.  
  1105. static PyObject *
  1106. text_getattr(tp, name)
  1107.     textobject *tp;
  1108.     char *name;
  1109. {
  1110.     PyObject *v = NULL;
  1111.     if (tp->t_ref == NULL) {
  1112.         PyErr_SetString(StdwinError, "text object already closed");
  1113.         return NULL;
  1114.     }
  1115.     if (strcmp(name, "__dict__") == 0) {
  1116.         v = tp->t_attr;
  1117.         if (v == NULL)
  1118.             v = Py_None;
  1119.     }
  1120.     else if (tp->t_attr != NULL) {
  1121.         v = PyDict_GetItemString(tp->t_attr, name);
  1122.     }
  1123.     if (v != NULL) {
  1124.         Py_INCREF(v);
  1125.         return v;
  1126.     }
  1127.     return Py_FindMethod(text_methods, (PyObject *)tp, name);
  1128. }
  1129.  
  1130. static int
  1131. text_setattr(tp, name, v)
  1132.     textobject *tp;
  1133.     char *name;
  1134.     PyObject *v;
  1135. {
  1136.     if (tp->t_attr == NULL) {
  1137.         tp->t_attr = PyDict_New();
  1138.         if (tp->t_attr == NULL)
  1139.             return -1;
  1140.     }
  1141.     if (v == NULL) {
  1142.         int rv = PyDict_DelItemString(tp->t_attr, name);
  1143.         if (rv < 0)
  1144.             PyErr_SetString(PyExc_AttributeError,
  1145.                   "delete non-existing text object attribute");
  1146.         return rv;
  1147.     }
  1148.     else
  1149.         return PyDict_SetItemString(tp->t_attr, name, v);
  1150. }
  1151.  
  1152. statichere PyTypeObject Texttype = {
  1153.     PyObject_HEAD_INIT(&PyType_Type)
  1154.     0,            /*ob_size*/
  1155.     "textedit",        /*tp_name*/
  1156.     sizeof(textobject),    /*tp_size*/
  1157.     0,            /*tp_itemsize*/
  1158.     /* methods */
  1159.     (destructor)text_dealloc, /*tp_dealloc*/
  1160.     0,            /*tp_print*/
  1161.     (getattrfunc)text_getattr, /*tp_getattr*/
  1162.     (setattrfunc)text_setattr, /*tp_setattr*/
  1163.     0,            /*tp_compare*/
  1164.     0,            /*tp_repr*/
  1165. };
  1166.  
  1167.  
  1168. /* Menu objects */
  1169.  
  1170. #define IDOFFSET 10        /* Menu IDs we use start here */
  1171. #define MAXNMENU 200        /* Max #menus we allow */
  1172. static menuobject *menulist[MAXNMENU];
  1173.  
  1174. static menuobject *newmenuobject Py_PROTO((char *));
  1175. static menuobject *
  1176. newmenuobject(title)
  1177.     char *title;
  1178. {
  1179.     int id;
  1180.     MENU *menu;
  1181.     menuobject *mp;
  1182.     for (id = 0; id < MAXNMENU; id++) {
  1183.         if (menulist[id] == NULL)
  1184.             break;
  1185.     }
  1186.     if (id >= MAXNMENU) {
  1187.         PyErr_SetString(StdwinError, "creating too many menus");
  1188.         return NULL;
  1189.     }
  1190.     menu = wmenucreate(id + IDOFFSET, title);
  1191.     if (menu == NULL)
  1192.         return (menuobject *) PyErr_NoMemory();
  1193.     mp = PyObject_NEW(menuobject, &Menutype);
  1194.     if (mp != NULL) {
  1195.         mp->m_menu = menu;
  1196.         mp->m_id = id + IDOFFSET;
  1197.         mp->m_attr = NULL;
  1198.         menulist[id] = mp;
  1199.     }
  1200.     else
  1201.         wmenudelete(menu);
  1202.     return mp;
  1203. }
  1204.  
  1205. /* Menu methods */
  1206.  
  1207. static void
  1208. menu_dealloc(mp)
  1209.     menuobject *mp;
  1210. {
  1211.     
  1212.     int id = mp->m_id - IDOFFSET;
  1213.     if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
  1214.         menulist[id] = NULL;
  1215.     }
  1216.     if (mp->m_menu != NULL)
  1217.         wmenudelete(mp->m_menu);
  1218.     Py_XDECREF(mp->m_attr);
  1219.     PyMem_DEL(mp);
  1220. }
  1221.  
  1222. static PyObject *
  1223. menu_close(mp, args)
  1224.     menuobject *mp;
  1225.     PyObject *args;
  1226. {
  1227.     int id = mp->m_id - IDOFFSET;
  1228.     if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
  1229.         menulist[id] = NULL;
  1230.     }
  1231.     mp->m_id = -1;
  1232.     if (mp->m_menu != NULL)
  1233.         wmenudelete(mp->m_menu);
  1234.     mp->m_menu = NULL;
  1235.     Py_XDECREF(mp->m_attr);
  1236.     mp->m_attr = NULL;
  1237.     Py_INCREF(Py_None);
  1238.     return Py_None;
  1239. }
  1240.  
  1241. static PyObject *
  1242. menu_additem(self, args)
  1243.     menuobject *self;
  1244.     PyObject *args;
  1245. {
  1246.     char *text;
  1247.     int shortcut = -1;
  1248.     if (PyTuple_Check(args)) {
  1249.         char c;
  1250.         if (!PyArg_Parse(args, "(sc)", &text, &c))
  1251.             return NULL;
  1252.         shortcut = c;
  1253.     }
  1254.     else if (!getstrarg(args, &text))
  1255.         return NULL;
  1256.     wmenuadditem(self->m_menu, text, shortcut);
  1257.     Py_INCREF(Py_None);
  1258.     return Py_None;
  1259. }
  1260.  
  1261. static PyObject *
  1262. menu_setitem(self, args)
  1263.     menuobject *self;
  1264.     PyObject *args;
  1265. {
  1266.     int index;
  1267.     char *text;
  1268.     if (!PyArg_Parse(args, "(is)", &index, &text))
  1269.         return NULL;
  1270.     wmenusetitem(self->m_menu, index, text);
  1271.     Py_INCREF(Py_None);
  1272.     return Py_None;
  1273. }
  1274.  
  1275. static PyObject *
  1276. menu_enable(self, args)
  1277.     menuobject *self;
  1278.     PyObject *args;
  1279. {
  1280.     int index;
  1281.     int flag;
  1282.     if (!PyArg_Parse(args, "(ii)", &index, &flag))
  1283.         return NULL;
  1284.     wmenuenable(self->m_menu, index, flag);
  1285.     Py_INCREF(Py_None);
  1286.     return Py_None;
  1287. }
  1288.  
  1289. static PyObject *
  1290. menu_check(self, args)
  1291.     menuobject *self;
  1292.     PyObject *args;
  1293. {
  1294.     int index;
  1295.     int flag;
  1296.     if (!PyArg_Parse(args, "(ii)", &index, &flag))
  1297.         return NULL;
  1298.     wmenucheck(self->m_menu, index, flag);
  1299.     Py_INCREF(Py_None);
  1300.     return Py_None;
  1301. }
  1302.  
  1303. static PyMethodDef menu_methods[] = {
  1304.     {"additem",    (PyCFunction)menu_additem},
  1305.     {"setitem",    (PyCFunction)menu_setitem},
  1306.     {"enable",    (PyCFunction)menu_enable},
  1307.     {"check",    (PyCFunction)menu_check},
  1308.     {"close",    (PyCFunction)menu_close},
  1309.     {NULL,        NULL}        /* sentinel */
  1310. };
  1311.  
  1312. static PyObject *
  1313. menu_getattr(mp, name)
  1314.     menuobject *mp;
  1315.     char *name;
  1316. {
  1317.     PyObject *v = NULL;
  1318.     if (mp->m_menu == NULL) {
  1319.         PyErr_SetString(StdwinError, "menu object already closed");
  1320.         return NULL;
  1321.     }
  1322.     if (strcmp(name, "__dict__") == 0) {
  1323.         v = mp->m_attr;
  1324.         if (v == NULL)
  1325.             v = Py_None;
  1326.     }
  1327.     else if (mp->m_attr != NULL) {
  1328.         v = PyDict_GetItemString(mp->m_attr, name);
  1329.     }
  1330.     if (v != NULL) {
  1331.         Py_INCREF(v);
  1332.         return v;
  1333.     }
  1334.     return Py_FindMethod(menu_methods, (PyObject *)mp, name);
  1335. }
  1336.  
  1337. static int
  1338. menu_setattr(mp, name, v)
  1339.     menuobject *mp;
  1340.     char *name;
  1341.     PyObject *v;
  1342. {
  1343.     if (mp->m_attr == NULL) {
  1344.         mp->m_attr = PyDict_New();
  1345.         if (mp->m_attr == NULL)
  1346.             return -1;
  1347.     }
  1348.     if (v == NULL) {
  1349.         int rv = PyDict_DelItemString(mp->m_attr, name);
  1350.         if (rv < 0)
  1351.             PyErr_SetString(PyExc_AttributeError,
  1352.                   "delete non-existing menu object attribute");
  1353.         return rv;
  1354.     }
  1355.     else
  1356.         return PyDict_SetItemString(mp->m_attr, name, v);
  1357. }
  1358.  
  1359. statichere PyTypeObject Menutype = {
  1360.     PyObject_HEAD_INIT(&PyType_Type)
  1361.     0,            /*ob_size*/
  1362.     "menu",            /*tp_name*/
  1363.     sizeof(menuobject),    /*tp_size*/
  1364.     0,            /*tp_itemsize*/
  1365.     /* methods */
  1366.     (destructor)menu_dealloc, /*tp_dealloc*/
  1367.     0,            /*tp_print*/
  1368.     (getattrfunc)menu_getattr, /*tp_getattr*/
  1369.     (setattrfunc)menu_setattr, /*tp_setattr*/
  1370.     0,            /*tp_compare*/
  1371.     0,            /*tp_repr*/
  1372. };
  1373.  
  1374.  
  1375. #ifdef HAVE_BITMAPS
  1376.  
  1377. /* Bitmaps objects */
  1378.  
  1379. static bitmapobject *newbitmapobject Py_PROTO((int, int));
  1380. static bitmapobject *
  1381. newbitmapobject(width, height)
  1382.     int width, height;
  1383. {
  1384.     BITMAP *bitmap;
  1385.     bitmapobject *bp;
  1386.     bitmap = wnewbitmap(width, height);
  1387.     if (bitmap == NULL)
  1388.         return (bitmapobject *) PyErr_NoMemory();
  1389.     bp = PyObject_NEW(bitmapobject, &Bitmaptype);
  1390.     if (bp != NULL) {
  1391.         bp->b_bitmap = bitmap;
  1392.         bp->b_attr = NULL;
  1393.     }
  1394.     else
  1395.         wfreebitmap(bitmap);
  1396.     return bp;
  1397. }
  1398.  
  1399. /* Bitmap methods */
  1400.  
  1401. static void
  1402. bitmap_dealloc(bp)
  1403.     bitmapobject *bp;
  1404. {
  1405.     if (bp->b_bitmap != NULL)
  1406.         wfreebitmap(bp->b_bitmap);
  1407.     Py_XDECREF(bp->b_attr);
  1408.     PyMem_DEL(bp);
  1409. }
  1410.  
  1411. static PyObject *
  1412. bitmap_close(bp, args)
  1413.     bitmapobject *bp;
  1414.     PyObject *args;
  1415. {
  1416.     if (bp->b_bitmap != NULL)
  1417.         wfreebitmap(bp->b_bitmap);
  1418.     bp->b_bitmap = NULL;
  1419.     Py_XDECREF(bp->b_attr);
  1420.     bp->b_attr = NULL;
  1421.     Py_INCREF(Py_None);
  1422.     return Py_None;
  1423. }
  1424.  
  1425. static PyObject *
  1426. bitmap_setbit(self, args)
  1427.     bitmapobject *self;
  1428.     PyObject *args;
  1429. {
  1430.     int a[3];
  1431.     if (!getpointintarg(args, a))
  1432.         return NULL;
  1433.     wsetbit(self->b_bitmap, a[0], a[1], a[2]);
  1434.     Py_INCREF(Py_None);
  1435.     return Py_None;
  1436. }
  1437.  
  1438. static PyObject *
  1439. bitmap_getbit(self, args)
  1440.     bitmapobject *self;
  1441.     PyObject *args;
  1442. {
  1443.     int a[2];
  1444.     if (!getpointarg(args, a))
  1445.         return NULL;
  1446.     return PyInt_FromLong((long) wgetbit(self->b_bitmap, a[0], a[1]));
  1447. }
  1448.  
  1449. static PyObject *
  1450. bitmap_getsize(self, args)
  1451.     bitmapobject *self;
  1452.     PyObject *args;
  1453. {
  1454.     int width, height;
  1455.     if (!PyArg_NoArgs(args))
  1456.         return NULL;
  1457.     wgetbitmapsize(self->b_bitmap, &width, &height);
  1458.     return Py_BuildValue("(ii)", width, height);
  1459. }
  1460.  
  1461. static PyMethodDef bitmap_methods[] = {
  1462.     {"close",    (PyCFunction)bitmap_close},
  1463.     {"getsize",    (PyCFunction)bitmap_getsize},
  1464.     {"getbit",    (PyCFunction)bitmap_getbit},
  1465.     {"setbit",    (PyCFunction)bitmap_setbit},
  1466.     {NULL,        NULL}        /* sentinel */
  1467. };
  1468.  
  1469. static PyObject *
  1470. bitmap_getattr(bp, name)
  1471.     bitmapobject *bp;
  1472.     char *name;
  1473. {
  1474.     PyObject *v = NULL;
  1475.     if (bp->b_bitmap == NULL) {
  1476.         PyErr_SetString(StdwinError, "bitmap object already closed");
  1477.         return NULL;
  1478.     }
  1479.     if (strcmp(name, "__dict__") == 0) {
  1480.         v = bp->b_attr;
  1481.         if (v == NULL)
  1482.             v = Py_None;
  1483.     }
  1484.     else if (bp->b_attr != NULL) {
  1485.         v = PyDict_GetItemString(bp->b_attr, name);
  1486.     }
  1487.     if (v != NULL) {
  1488.         Py_INCREF(v);
  1489.         return v;
  1490.     }
  1491.     return Py_FindMethod(bitmap_methods, (PyObject *)bp, name);
  1492. }
  1493.  
  1494. static int
  1495. bitmap_setattr(bp, name, v)
  1496.     bitmapobject *bp;
  1497.     char *name;
  1498.     PyObject *v;
  1499. {
  1500.     if (bp->b_attr == NULL) {
  1501.         bp->b_attr = PyDict_New();
  1502.         if (bp->b_attr == NULL)
  1503.             return -1;
  1504.     }
  1505.     if (v == NULL) {
  1506.         int rv = PyDict_DelItemString(bp->b_attr, name);
  1507.         if (rv < 0)
  1508.             PyErr_SetString(PyExc_AttributeError,
  1509.                     "delete non-existing bitmap object attribute");
  1510.         return rv;
  1511.     }
  1512.     else
  1513.         return PyDict_SetItemString(bp->b_attr, name, v);
  1514. }
  1515.  
  1516. statichere PyTypeObject Bitmaptype = {
  1517.     PyObject_HEAD_INIT(&PyType_Type)
  1518.     0,            /*ob_size*/
  1519.     "bitmap",            /*tp_name*/
  1520.     sizeof(bitmapobject),    /*tp_size*/
  1521.     0,            /*tp_itemsize*/
  1522.     /* methods */
  1523.     (destructor)bitmap_dealloc, /*tp_dealloc*/
  1524.     0,            /*tp_print*/
  1525.     (getattrfunc)bitmap_getattr, /*tp_getattr*/
  1526.     (setattrfunc)bitmap_setattr, /*tp_setattr*/
  1527.     0,            /*tp_compare*/
  1528.     0,            /*tp_repr*/
  1529. };
  1530.  
  1531. #endif /* HAVE_BITMAPS */
  1532.  
  1533.  
  1534. /* Windows */
  1535.  
  1536. #define MAXNWIN 50
  1537. static windowobject *windowlist[MAXNWIN];
  1538.  
  1539. /* Window methods */
  1540.  
  1541. static void
  1542. window_dealloc(wp)
  1543.     windowobject *wp;
  1544. {
  1545.     if (wp->w_win != NULL) {
  1546.         int tag = wgettag(wp->w_win);
  1547.         if (tag >= 0 && tag < MAXNWIN)
  1548.             windowlist[tag] = NULL;
  1549.         else
  1550.             fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
  1551.                 tag);
  1552.         wclose(wp->w_win);
  1553.     }
  1554.     Py_DECREF(wp->w_title);
  1555.     if (wp->w_attr != NULL)
  1556.         Py_DECREF(wp->w_attr);
  1557.     free((char *)wp);
  1558. }
  1559.  
  1560. static PyObject *
  1561. window_close(wp, args)
  1562.     windowobject *wp;
  1563.     PyObject *args;
  1564. {
  1565.     if (wp->w_win != NULL) {
  1566.         int tag = wgettag(wp->w_win);
  1567.         if (tag >= 0 && tag < MAXNWIN)
  1568.             windowlist[tag] = NULL;
  1569.         wclose(wp->w_win);
  1570.         wp->w_win = NULL;
  1571.     }
  1572.     Py_INCREF(Py_None);
  1573.     return Py_None;
  1574. }
  1575.  
  1576. static PyObject *
  1577. window_begindrawing(wp, args)
  1578.     windowobject *wp;
  1579.     PyObject *args;
  1580. {
  1581.     drawingobject *dp;
  1582.     if (!PyArg_NoArgs(args))
  1583.         return NULL;
  1584.     if (Drawing != NULL) {
  1585.         PyErr_SetString(StdwinError, "already drawing");
  1586.         return NULL;
  1587.     }
  1588.     dp = PyObject_NEW(drawingobject, &Drawingtype);
  1589.     if (dp == NULL)
  1590.         return NULL;
  1591.     Drawing = dp;
  1592.     Py_INCREF(wp);
  1593.     dp->d_ref = wp;
  1594.     wbegindrawing(wp->w_win);
  1595.     return (PyObject *)dp;
  1596. }
  1597.  
  1598. static PyObject *
  1599. window_change(wp, args)
  1600.     windowobject *wp;
  1601.     PyObject *args;
  1602. {
  1603.     int a[4];
  1604.     if (!getrectarg(args, a))
  1605.         return NULL;
  1606.     wchange(wp->w_win, a[0], a[1], a[2], a[3]);
  1607.     Py_INCREF(Py_None);
  1608.     return Py_None;
  1609. }
  1610.  
  1611. static PyObject *
  1612. window_gettitle(wp, args)
  1613.     windowobject *wp;
  1614.     PyObject *args;
  1615. {
  1616.     if (!PyArg_NoArgs(args))
  1617.         return NULL;
  1618.     Py_INCREF(wp->w_title);
  1619.     return wp->w_title;
  1620. }
  1621.  
  1622. static PyObject *
  1623. window_getwinpos(wp, args)
  1624.     windowobject *wp;
  1625.     PyObject *args;
  1626. {
  1627.     int h, v;
  1628.     if (!PyArg_NoArgs(args))
  1629.         return NULL;
  1630.     wgetwinpos(wp->w_win, &h, &v);
  1631.     return makepoint(h, v);
  1632. }
  1633.  
  1634. static PyObject *
  1635. window_getwinsize(wp, args)
  1636.     windowobject *wp;
  1637.     PyObject *args;
  1638. {
  1639.     int width, height;
  1640.     if (!PyArg_NoArgs(args))
  1641.         return NULL;
  1642.     wgetwinsize(wp->w_win, &width, &height);
  1643.     return makepoint(width, height);
  1644. }
  1645.  
  1646. static PyObject *
  1647. window_setwinpos(wp, args)
  1648.     windowobject *wp;
  1649.     PyObject *args;
  1650. {
  1651.     int a[2];
  1652.     if (!getpointarg(args, a))
  1653.         return NULL;
  1654.     wsetwinpos(wp->w_win, a[0], a[1]);
  1655.     Py_INCREF(Py_None);
  1656.     return Py_None;
  1657. }
  1658.  
  1659. static PyObject *
  1660. window_setwinsize(wp, args)
  1661.     windowobject *wp;
  1662.     PyObject *args;
  1663. {
  1664.     int a[2];
  1665.     if (!getpointarg(args, a))
  1666.         return NULL;
  1667.     wsetwinsize(wp->w_win, a[0], a[1]);
  1668.     Py_INCREF(Py_None);
  1669.     return Py_None;
  1670. }
  1671.  
  1672. static PyObject *
  1673. window_getdocsize(wp, args)
  1674.     windowobject *wp;
  1675.     PyObject *args;
  1676. {
  1677.     int width, height;
  1678.     if (!PyArg_NoArgs(args))
  1679.         return NULL;
  1680.     wgetdocsize(wp->w_win, &width, &height);
  1681.     return makepoint(width, height);
  1682. }
  1683.  
  1684. static PyObject *
  1685. window_getorigin(wp, args)
  1686.     windowobject *wp;
  1687.     PyObject *args;
  1688. {
  1689.     int width, height;
  1690.     if (!PyArg_NoArgs(args))
  1691.         return NULL;
  1692.     wgetorigin(wp->w_win, &width, &height);
  1693.     return makepoint(width, height);
  1694. }
  1695.  
  1696. static PyObject *
  1697. window_scroll(wp, args)
  1698.     windowobject *wp;
  1699.     PyObject *args;
  1700. {
  1701.     int a[6];
  1702.     if (!getrectpointarg(args, a))
  1703.         return NULL;
  1704.     wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
  1705.     Py_INCREF(Py_None);
  1706.     return Py_None;
  1707. }
  1708.  
  1709. static PyObject *
  1710. window_setdocsize(wp, args)
  1711.     windowobject *wp;
  1712.     PyObject *args;
  1713. {
  1714.     int a[2];
  1715.     if (!getpointarg(args, a))
  1716.         return NULL;
  1717.     wsetdocsize(wp->w_win, a[0], a[1]);
  1718.     Py_INCREF(Py_None);
  1719.     return Py_None;
  1720. }
  1721.  
  1722. static PyObject *
  1723. window_setorigin(wp, args)
  1724.     windowobject *wp;
  1725.     PyObject *args;
  1726. {
  1727.     int a[2];
  1728.     if (!getpointarg(args, a))
  1729.         return NULL;
  1730.     wsetorigin(wp->w_win, a[0], a[1]);
  1731.     Py_INCREF(Py_None);
  1732.     return Py_None;
  1733. }
  1734.  
  1735. static PyObject *
  1736. window_settitle(wp, args)
  1737.     windowobject *wp;
  1738.     PyObject *args;
  1739. {
  1740.     PyObject *title;
  1741.     if (!PyArg_Parse(args, "S", &title))
  1742.         return NULL;
  1743.     Py_DECREF(wp->w_title);
  1744.     Py_INCREF(title);
  1745.     wp->w_title = title;
  1746.     wsettitle(wp->w_win, PyString_AsString(title));
  1747.     Py_INCREF(Py_None);
  1748.     return Py_None;
  1749. }
  1750.  
  1751. static PyObject *
  1752. window_show(wp, args)
  1753.     windowobject *wp;
  1754.     PyObject *args;
  1755. {
  1756.     int a[4];
  1757.     if (!getrectarg(args, a))
  1758.         return NULL;
  1759.     wshow(wp->w_win, a[0], a[1], a[2], a[3]);
  1760.     Py_INCREF(Py_None);
  1761.     return Py_None;
  1762. }
  1763.  
  1764. static PyObject *
  1765. window_settimer(wp, args)
  1766.     windowobject *wp;
  1767.     PyObject *args;
  1768. {
  1769.     int a;
  1770.     if (!getintarg(args, &a))
  1771.         return NULL;
  1772.     wsettimer(wp->w_win, a);
  1773.     Py_INCREF(Py_None);
  1774.     return Py_None;
  1775. }
  1776.  
  1777. static PyObject *
  1778. window_menucreate(self, args)
  1779.     windowobject *self;
  1780.     PyObject *args;
  1781. {
  1782.     menuobject *mp;
  1783.     char *title;
  1784.     if (!getstrarg(args, &title))
  1785.         return NULL;
  1786.     wmenusetdeflocal(1);
  1787.     mp = newmenuobject(title);
  1788.     if (mp == NULL)
  1789.         return NULL;
  1790.     wmenuattach(self->w_win, mp->m_menu);
  1791.     return (PyObject *)mp;
  1792. }
  1793.  
  1794. static PyObject *
  1795. window_textcreate(self, args)
  1796.     windowobject *self;
  1797.     PyObject *args;
  1798. {
  1799.     int a[4];
  1800.     if (!getrectarg(args, a))
  1801.         return NULL;
  1802.     return (PyObject *)newtextobject(self, a[0], a[1], a[2], a[3]);
  1803. }
  1804.  
  1805. static PyObject *
  1806. window_setselection(self, args)
  1807.     windowobject *self;
  1808.     PyObject *args;
  1809. {
  1810.     int sel, size, ok;
  1811.     char *text;
  1812.     if (!PyArg_Parse(args, "(it#)", &sel, &text, &size))
  1813.         return NULL;
  1814.     ok = wsetselection(self->w_win, sel, text, size);
  1815.     return PyInt_FromLong(ok);
  1816. }
  1817.  
  1818. static PyObject *
  1819. window_setwincursor(self, args)
  1820.     windowobject *self;
  1821.     PyObject *args;
  1822. {
  1823.     char *name;
  1824.     CURSOR *c;
  1825.     if (!PyArg_Parse(args, "z", &name))
  1826.         return NULL;
  1827.     if (name == NULL)
  1828.         c = NULL;
  1829.     else {
  1830.         c = wfetchcursor(name);
  1831.         if (c == NULL) {
  1832.             PyErr_SetString(StdwinError, "no such cursor");
  1833.             return NULL;
  1834.         }
  1835.     }
  1836.     wsetwincursor(self->w_win, c);
  1837.     Py_INCREF(Py_None);
  1838.     return Py_None;
  1839. }
  1840.  
  1841. static PyObject *
  1842. window_setactive(self, args)
  1843.     windowobject *self;
  1844.     PyObject *args;
  1845. {
  1846.     if (!PyArg_NoArgs(args))
  1847.         return NULL;
  1848.     wsetactive(self->w_win);
  1849.     Py_INCREF(Py_None);
  1850.     return Py_None;
  1851. }
  1852.  
  1853. #ifdef CWI_HACKS
  1854. static PyObject *
  1855. window_getxwindowid(self, args)
  1856.     windowobject *self;
  1857.     PyObject *args;
  1858. {
  1859.     long wid = wgetxwindowid(self->w_win);
  1860.     return PyInt_FromLong(wid);
  1861. }
  1862. #endif
  1863.  
  1864. static PyMethodDef window_methods[] = {
  1865.     {"begindrawing",(PyCFunction)window_begindrawing},
  1866.     {"change",    (PyCFunction)window_change},
  1867.     {"close",    (PyCFunction)window_close},
  1868.     {"getdocsize",    (PyCFunction)window_getdocsize},
  1869.     {"getorigin",    (PyCFunction)window_getorigin},
  1870.     {"gettitle",    (PyCFunction)window_gettitle},
  1871.     {"getwinpos",    (PyCFunction)window_getwinpos},
  1872.     {"getwinsize",    (PyCFunction)window_getwinsize},
  1873.     {"menucreate",    (PyCFunction)window_menucreate},
  1874.     {"scroll",    (PyCFunction)window_scroll},
  1875.     {"setactive",    (PyCFunction)window_setactive},
  1876.     {"setdocsize",    (PyCFunction)window_setdocsize},
  1877.     {"setorigin",    (PyCFunction)window_setorigin},
  1878.     {"setselection",(PyCFunction)window_setselection},
  1879.     {"settimer",    (PyCFunction)window_settimer},
  1880.     {"settitle",    (PyCFunction)window_settitle},
  1881.     {"setwincursor",(PyCFunction)window_setwincursor},
  1882.     {"setwinpos",    (PyCFunction)window_setwinpos},
  1883.     {"setwinsize",    (PyCFunction)window_setwinsize},
  1884.     {"show",    (PyCFunction)window_show},
  1885.     {"textcreate",    (PyCFunction)window_textcreate},
  1886. #ifdef CWI_HACKS
  1887.     {"getxwindowid",(PyCFunction)window_getxwindowid},
  1888. #endif
  1889.     {NULL,        NULL}        /* sentinel */
  1890. };
  1891.  
  1892. static PyObject *
  1893. window_getattr(wp, name)
  1894.     windowobject *wp;
  1895.     char *name;
  1896. {
  1897.     PyObject *v = NULL;
  1898.     if (wp->w_win == NULL) {
  1899.         PyErr_SetString(StdwinError, "window already closed");
  1900.         return NULL;
  1901.     }
  1902.     if (strcmp(name, "__dict__") == 0) {
  1903.         v = wp->w_attr;
  1904.         if (v == NULL)
  1905.             v = Py_None;
  1906.     }
  1907.     else if (wp->w_attr != NULL) {
  1908.         v = PyDict_GetItemString(wp->w_attr, name);
  1909.     }
  1910.     if (v != NULL) {
  1911.         Py_INCREF(v);
  1912.         return v;
  1913.     }
  1914.     return Py_FindMethod(window_methods, (PyObject *)wp, name);
  1915. }
  1916.  
  1917. static int
  1918. window_setattr(wp, name, v)
  1919.     windowobject *wp;
  1920.     char *name;
  1921.     PyObject *v;
  1922. {
  1923.     if (wp->w_attr == NULL) {
  1924.         wp->w_attr = PyDict_New();
  1925.         if (wp->w_attr == NULL)
  1926.             return -1;
  1927.     }
  1928.     if (v == NULL) {
  1929.         int rv = PyDict_DelItemString(wp->w_attr, name);
  1930.         if (rv < 0)
  1931.             PyErr_SetString(PyExc_AttributeError,
  1932.                       "delete non-existing menu object attribute");
  1933.         return rv;
  1934.     }
  1935.     else
  1936.         return PyDict_SetItemString(wp->w_attr, name, v);
  1937. }
  1938.  
  1939. statichere PyTypeObject Windowtype = {
  1940.     PyObject_HEAD_INIT(&PyType_Type)
  1941.     0,            /*ob_size*/
  1942.     "window",        /*tp_name*/
  1943.     sizeof(windowobject),    /*tp_size*/
  1944.     0,            /*tp_itemsize*/
  1945.     /* methods */
  1946.     (destructor)window_dealloc, /*tp_dealloc*/
  1947.     0,            /*tp_print*/
  1948.     (getattrfunc)window_getattr, /*tp_getattr*/
  1949.     (setattrfunc)window_setattr, /*tp_setattr*/
  1950.     0,            /*tp_compare*/
  1951.     0,            /*tp_repr*/
  1952. };
  1953.  
  1954. /* Stdwin methods */
  1955.  
  1956. static PyObject *
  1957. stdwin_done(sw, args)
  1958.     PyObject *sw;
  1959.     PyObject *args;
  1960. {
  1961.     if (!PyArg_NoArgs(args))
  1962.         return NULL;
  1963.     wdone();
  1964.     /* XXX There is no protection against continued use of
  1965.        XXX stdwin functions or objects after this call is made.
  1966.        XXX Use at own risk */
  1967.     Py_INCREF(Py_None);
  1968.     return Py_None;
  1969. }
  1970.  
  1971. static PyObject *
  1972. stdwin_open(sw, args)
  1973.     PyObject *sw;
  1974.     PyObject *args;
  1975. {
  1976.     int tag;
  1977.     PyObject *title;
  1978.     windowobject *wp;
  1979.     if (!PyArg_Parse(args, "S", &title))
  1980.         return NULL;
  1981.     for (tag = 0; tag < MAXNWIN; tag++) {
  1982.         if (windowlist[tag] == NULL)
  1983.             break;
  1984.     }
  1985.     if (tag >= MAXNWIN) {
  1986.         PyErr_SetString(StdwinError, "creating too many windows");
  1987.         return NULL;
  1988.     }
  1989.     wp = PyObject_NEW(windowobject, &Windowtype);
  1990.     if (wp == NULL)
  1991.         return NULL;
  1992.     Py_INCREF(title);
  1993.     wp->w_title = title;
  1994.     wp->w_win = wopen(PyString_AsString(title), (void (*)()) NULL);
  1995.     wp->w_attr = NULL;
  1996.     if (wp->w_win == NULL) {
  1997.         Py_DECREF(wp);
  1998.         return NULL;
  1999.     }
  2000.     windowlist[tag] = wp;
  2001.     wsettag(wp->w_win, tag);
  2002.     return (PyObject *)wp;
  2003. }
  2004.  
  2005. static PyObject *
  2006. window2object(win)
  2007.     WINDOW *win;
  2008. {
  2009.     PyObject *w;
  2010.     if (win == NULL)
  2011.         w = Py_None;
  2012.     else {
  2013.         int tag = wgettag(win);
  2014.         if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL ||
  2015.             windowlist[tag]->w_win != win)
  2016.             w = Py_None;
  2017.         else
  2018.             w = (PyObject *)windowlist[tag];
  2019.     }
  2020.     Py_INCREF(w);
  2021.     return w;
  2022. }
  2023.  
  2024. static PyObject *
  2025. stdwin_get_poll_event(poll, args)
  2026.     int poll;
  2027.     PyObject *args;
  2028. {
  2029.     EVENT e;
  2030.     PyObject *u, *v, *w;
  2031.     if (!PyArg_NoArgs(args))
  2032.         return NULL;
  2033.     if (Drawing != NULL) {
  2034.         PyErr_SetString(StdwinError,
  2035.                 "cannot getevent() while drawing");
  2036.         return NULL;
  2037.     }
  2038.  again:
  2039.     BGN_STDWIN
  2040.     if (poll) {
  2041.         if (!wpollevent(&e)) {
  2042.             RET_STDWIN
  2043.             Py_INCREF(Py_None);
  2044.             return Py_None;
  2045.         }
  2046.     }
  2047.     else
  2048.         wgetevent(&e);
  2049.     END_STDWIN
  2050.     if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
  2051.         /* Turn keyboard interrupts into exceptions */
  2052.         PyErr_SetNone(PyExc_KeyboardInterrupt);
  2053.         return NULL;
  2054.     }
  2055.     if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) {
  2056.         /* Turn WC_CLOSE commands into WE_CLOSE events */
  2057.         e.type = WE_CLOSE;
  2058.     }
  2059.     v = window2object(e.window);
  2060.     switch (e.type) {
  2061.     case WE_CHAR:
  2062.         {
  2063.             char c[1];
  2064.             c[0] = e.u.character;
  2065.             w = PyString_FromStringAndSize(c, 1);
  2066.         }
  2067.         break;
  2068.     case WE_COMMAND:
  2069.         w = PyInt_FromLong((long)e.u.command);
  2070.         break;
  2071.     case WE_DRAW:
  2072.         w = makerect(e.u.area.left, e.u.area.top,
  2073.                 e.u.area.right, e.u.area.bottom);
  2074.         break;
  2075.     case WE_MOUSE_DOWN:
  2076.     case WE_MOUSE_MOVE:
  2077.     case WE_MOUSE_UP:
  2078.         w = Py_BuildValue("((ii)iii)",
  2079.                   e.u.where.h, e.u.where.v,
  2080.                   e.u.where.clicks,
  2081.                   e.u.where.button,
  2082.                   e.u.where.mask);
  2083.         break;
  2084.     case WE_MENU:
  2085.         if (e.u.m.id >= IDOFFSET &&
  2086.             e.u.m.id < IDOFFSET+MAXNMENU &&
  2087.             menulist[e.u.m.id - IDOFFSET] != NULL)
  2088.         {
  2089.             w = Py_BuildValue("(Oi)",
  2090.                       menulist[e.u.m.id - IDOFFSET],
  2091.                       e.u.m.item);
  2092.         }
  2093.         else {
  2094.             /* Ghost menu event.
  2095.                Can occur only on the Mac if another part
  2096.                of the aplication has installed a menu;
  2097.                like the THINK C console library. */
  2098.             Py_DECREF(v);
  2099.             goto again;
  2100.         }
  2101.         break;
  2102.     case WE_KEY:
  2103.         w = Py_BuildValue("(ii)", e.u.key.code, e.u.key.mask);
  2104.         break;
  2105.     case WE_LOST_SEL:
  2106.         w = PyInt_FromLong((long)e.u.sel);
  2107.         break;
  2108.     default:
  2109.         w = Py_None;
  2110.         Py_INCREF(w);
  2111.         break;
  2112.     }
  2113.     if (w == NULL) {
  2114.         Py_DECREF(v);
  2115.         return NULL;
  2116.     }
  2117.     u = Py_BuildValue("(iOO)", e.type, v, w);
  2118.     Py_XDECREF(v);
  2119.     Py_XDECREF(w);
  2120.     return u;
  2121. }
  2122.  
  2123. static PyObject *
  2124. stdwin_getevent(sw, args)
  2125.     PyObject *sw;
  2126.     PyObject *args;
  2127. {
  2128.     return stdwin_get_poll_event(0, args);
  2129. }
  2130.  
  2131. static PyObject *
  2132. stdwin_pollevent(sw, args)
  2133.     PyObject *sw;
  2134.     PyObject *args;
  2135. {
  2136.     return stdwin_get_poll_event(1, args);
  2137. }
  2138.  
  2139. static PyObject *
  2140. stdwin_setdefwinpos(sw, args)
  2141.     PyObject *sw;
  2142.     PyObject *args;
  2143. {
  2144.     int a[2];
  2145.     if (!getpointarg(args, a))
  2146.         return NULL;
  2147.     wsetdefwinpos(a[0], a[1]);
  2148.     Py_INCREF(Py_None);
  2149.     return Py_None;
  2150. }
  2151.  
  2152. static PyObject *
  2153. stdwin_setdefwinsize(sw, args)
  2154.     PyObject *sw;
  2155.     PyObject *args;
  2156. {
  2157.     int a[2];
  2158.     if (!getpointarg(args, a))
  2159.         return NULL;
  2160.     wsetdefwinsize(a[0], a[1]);
  2161.     Py_INCREF(Py_None);
  2162.     return Py_None;
  2163. }
  2164.  
  2165. static PyObject *
  2166. stdwin_setdefscrollbars(sw, args)
  2167.     PyObject *sw;
  2168.     PyObject *args;
  2169. {
  2170.     int a[2];
  2171.     if (!getpointarg(args, a))
  2172.         return NULL;
  2173.     wsetdefscrollbars(a[0], a[1]);
  2174.     Py_INCREF(Py_None);
  2175.     return Py_None;
  2176. }
  2177.  
  2178. static PyObject *
  2179. stdwin_getdefwinpos(self, args)
  2180.     PyObject *self;
  2181.     PyObject *args;
  2182. {
  2183.     int h, v;
  2184.     if (!PyArg_NoArgs(args))
  2185.         return NULL;
  2186.     wgetdefwinpos(&h, &v);
  2187.     return makepoint(h, v);
  2188. }
  2189.  
  2190. static PyObject *
  2191. stdwin_getdefwinsize(self, args)
  2192.     PyObject *self;
  2193.     PyObject *args;
  2194. {
  2195.     int width, height;
  2196.     if (!PyArg_NoArgs(args))
  2197.         return NULL;
  2198.     wgetdefwinsize(&width, &height);
  2199.     return makepoint(width, height);
  2200. }
  2201.  
  2202. static PyObject *
  2203. stdwin_getdefscrollbars(self, args)
  2204.     PyObject *self;
  2205.     PyObject *args;
  2206. {
  2207.     int h, v;
  2208.     if (!PyArg_NoArgs(args))
  2209.         return NULL;
  2210.     wgetdefscrollbars(&h, &v);
  2211.     return makepoint(h, v);
  2212. }
  2213.  
  2214. static PyObject *
  2215. stdwin_menucreate(self, args)
  2216.     PyObject *self;
  2217.     PyObject *args;
  2218. {
  2219.     char *title;
  2220.     if (!getstrarg(args, &title))
  2221.         return NULL;
  2222.     wmenusetdeflocal(0);
  2223.     return (PyObject *)newmenuobject(title);
  2224. }
  2225.  
  2226. static PyObject *
  2227. stdwin_askfile(self, args)
  2228.     PyObject *self;
  2229.     PyObject *args;
  2230. {
  2231.     char *prompt, *dflt;
  2232.     int new, ret;
  2233.     char buf[256];
  2234.     if (!PyArg_Parse(args, "(ssi)", &prompt, &dflt, &new))
  2235.         return NULL;
  2236.     strncpy(buf, dflt, sizeof buf);
  2237.     buf[sizeof buf - 1] = '\0';
  2238.     BGN_STDWIN
  2239.     ret = waskfile(prompt, buf, sizeof buf, new);
  2240.     END_STDWIN
  2241.     if (!ret) {
  2242.         PyErr_SetNone(PyExc_KeyboardInterrupt);
  2243.         return NULL;
  2244.     }
  2245.     return PyString_FromString(buf);
  2246. }
  2247.  
  2248. static PyObject *
  2249. stdwin_askync(self, args)
  2250.     PyObject *self;
  2251.     PyObject *args;
  2252. {
  2253.     char *prompt;
  2254.     int new, ret;
  2255.     if (!PyArg_Parse(args, "(si)", &prompt, &new))
  2256.         return NULL;
  2257.     BGN_STDWIN
  2258.     ret = waskync(prompt, new);
  2259.     END_STDWIN
  2260.     if (ret < 0) {
  2261.         PyErr_SetNone(PyExc_KeyboardInterrupt);
  2262.         return NULL;
  2263.     }
  2264.     return PyInt_FromLong((long)ret);
  2265. }
  2266.  
  2267. static PyObject *
  2268. stdwin_askstr(self, args)
  2269.     PyObject *self;
  2270.     PyObject *args;
  2271. {
  2272.     char *prompt, *dflt;
  2273.     int ret;
  2274.     char buf[256];
  2275.     if (!PyArg_Parse(args, "(ss)", &prompt, &dflt))
  2276.         return NULL;
  2277.     strncpy(buf, dflt, sizeof buf);
  2278.     buf[sizeof buf - 1] = '\0';
  2279.     BGN_STDWIN
  2280.     ret = waskstr(prompt, buf, sizeof buf);
  2281.     END_STDWIN
  2282.     if (!ret) {
  2283.         PyErr_SetNone(PyExc_KeyboardInterrupt);
  2284.         return NULL;
  2285.     }
  2286.     return PyString_FromString(buf);
  2287. }
  2288.  
  2289. static PyObject *
  2290. stdwin_message(self, args)
  2291.     PyObject *self;
  2292.     PyObject *args;
  2293. {
  2294.     char *msg;
  2295.     if (!getstrarg(args, &msg))
  2296.         return NULL;
  2297.     BGN_STDWIN
  2298.     wmessage(msg);
  2299.     END_STDWIN
  2300.     Py_INCREF(Py_None);
  2301.     return Py_None;
  2302. }
  2303.  
  2304. static PyObject *
  2305. stdwin_fleep(self, args)
  2306.     PyObject *self;
  2307.     PyObject *args;
  2308. {
  2309.     if (!PyArg_NoArgs(args))
  2310.         return NULL;
  2311.     wfleep();
  2312.     Py_INCREF(Py_None);
  2313.     return Py_None;
  2314. }
  2315.  
  2316. static PyObject *
  2317. stdwin_setcutbuffer(self, args)
  2318.     PyObject *self;
  2319.     PyObject *args;
  2320. {
  2321.     int i, size;
  2322.     char *str;
  2323.     if (!PyArg_Parse(args, "(it#)", &i, &str, &size))
  2324.         return NULL;
  2325.     wsetcutbuffer(i, str, size);
  2326.     Py_INCREF(Py_None);
  2327.     return Py_None;
  2328. }
  2329.  
  2330. static PyObject *
  2331. stdwin_getactive(self, args)
  2332.     PyObject *self;
  2333.     PyObject *args;
  2334. {
  2335.     return window2object(wgetactive());
  2336. }
  2337.  
  2338. static PyObject *
  2339. stdwin_getcutbuffer(self, args)
  2340.     PyObject *self;
  2341.     PyObject *args;
  2342. {
  2343.     int i;
  2344.     char *str;
  2345.     int len;
  2346.     if (!getintarg(args, &i))
  2347.         return NULL;
  2348.     str = wgetcutbuffer(i, &len);
  2349.     if (str == NULL) {
  2350.         str = "";
  2351.         len = 0;
  2352.     }
  2353.     return PyString_FromStringAndSize(str, len);
  2354. }
  2355.  
  2356. static PyObject *
  2357. stdwin_rotatecutbuffers(self, args)
  2358.     PyObject *self;
  2359.     PyObject *args;
  2360. {
  2361.     int i;
  2362.     if (!getintarg(args, &i))
  2363.         return NULL;
  2364.     wrotatecutbuffers(i);
  2365.     Py_INCREF(Py_None);
  2366.     return Py_None;
  2367. }
  2368.  
  2369. static PyObject *
  2370. stdwin_getselection(self, args)
  2371.     PyObject *self;
  2372.     PyObject *args;
  2373. {
  2374.     int sel;
  2375.     char *data;
  2376.     int len;
  2377.     if (!getintarg(args, &sel))
  2378.         return NULL;
  2379.     data = wgetselection(sel, &len);
  2380.     if (data == NULL) {
  2381.         data = "";
  2382.         len = 0;
  2383.     }
  2384.     return PyString_FromStringAndSize(data, len);
  2385. }
  2386.  
  2387. static PyObject *
  2388. stdwin_resetselection(self, args)
  2389.     PyObject *self;
  2390.     PyObject *args;
  2391. {
  2392.     int sel;
  2393.     if (!getintarg(args, &sel))
  2394.         return NULL;
  2395.     wresetselection(sel);
  2396.     Py_INCREF(Py_None);
  2397.     return Py_None;
  2398. }
  2399.  
  2400. static PyObject *
  2401. stdwin_fetchcolor(self, args)
  2402.     PyObject *self;
  2403.     PyObject *args;
  2404. {
  2405.     char *colorname;
  2406.     COLOR color;
  2407.     if (!getstrarg(args, &colorname))
  2408.         return NULL;
  2409.     color = wfetchcolor(colorname);
  2410. #ifdef BADCOLOR
  2411.     if (color == BADCOLOR) {
  2412.         PyErr_SetString(StdwinError, "color name not found");
  2413.         return NULL;
  2414.     }
  2415. #endif
  2416.     return PyInt_FromLong((long)color);
  2417. }
  2418.  
  2419. static PyObject *
  2420. stdwin_getscrsize(self, args)
  2421.     PyObject *self;
  2422.     PyObject *args;
  2423. {
  2424.     int width, height;
  2425.     if (!PyArg_NoArgs(args))
  2426.         return NULL;
  2427.     wgetscrsize(&width, &height);
  2428.     return makepoint(width, height);
  2429. }
  2430.  
  2431. static PyObject *
  2432. stdwin_getscrmm(self, args)
  2433.     PyObject *self;
  2434.     PyObject *args;
  2435. {
  2436.     int width, height;
  2437.     if (!PyArg_NoArgs(args))
  2438.         return NULL;
  2439.     wgetscrmm(&width, &height);
  2440.     return makepoint(width, height);
  2441. }
  2442.  
  2443. #ifdef unix
  2444. static PyObject *
  2445. stdwin_connectionnumber(self, args)
  2446.     PyObject *self;
  2447.     PyObject *args;
  2448. {
  2449.     if (!PyArg_NoArgs(args))
  2450.         return NULL;
  2451.     return PyInt_FromLong((long) wconnectionnumber());
  2452. }
  2453. #endif
  2454.  
  2455. static PyObject *
  2456. stdwin_listfontnames(self, args)
  2457.     PyObject *self;
  2458.     PyObject *args;
  2459. {
  2460.     char *pattern;
  2461.     char **fontnames;
  2462.     int count;
  2463.     PyObject *list;
  2464.     if (!PyArg_Parse(args, "z", &pattern))
  2465.         return NULL;
  2466.     fontnames = wlistfontnames(pattern, &count);
  2467.     list = PyList_New(count);
  2468.     if (list != NULL) {
  2469.         int i;
  2470.         for (i = 0; i < count; i++) {
  2471.             PyObject *v = PyString_FromString(fontnames[i]);
  2472.             if (v == NULL) {
  2473.                 Py_DECREF(list);
  2474.                 list = NULL;
  2475.                 break;
  2476.             }
  2477.             PyList_SetItem(list, i, v);
  2478.         }
  2479.     }
  2480.     return list;
  2481. }
  2482.  
  2483. #ifdef HAVE_BITMAPS
  2484. static PyObject *
  2485. stdwin_newbitmap(self, args)
  2486.     PyObject *self;
  2487.     PyObject *args;
  2488. {
  2489.     int width, height;
  2490.     bitmapobject *bp;
  2491.     if (!PyArg_Parse(args, "(ii)", &width, &height))
  2492.         return NULL;
  2493.     return (PyObject *)newbitmapobject(width, height);
  2494. }
  2495. #endif
  2496.  
  2497. static PyMethodDef stdwin_methods[] = {
  2498.     {"askfile",        stdwin_askfile},
  2499.     {"askstr",        stdwin_askstr},
  2500.     {"askync",        stdwin_askync},
  2501.     {"done",        stdwin_done},
  2502.     {"fetchcolor",        stdwin_fetchcolor},
  2503. #ifdef unix
  2504.     {"fileno",        stdwin_connectionnumber},
  2505.     {"connectionnumber",    stdwin_connectionnumber},
  2506. #endif
  2507.     {"fleep",        stdwin_fleep},
  2508.     {"getactive",        stdwin_getactive},
  2509.     {"getcutbuffer",    stdwin_getcutbuffer},
  2510.     {"getdefscrollbars",    stdwin_getdefscrollbars},
  2511.     {"getdefwinpos",    stdwin_getdefwinpos},
  2512.     {"getdefwinsize",    stdwin_getdefwinsize},
  2513.     {"getevent",        stdwin_getevent},
  2514.     {"getscrmm",        stdwin_getscrmm},
  2515.     {"getscrsize",        stdwin_getscrsize},
  2516.     {"getselection",    stdwin_getselection},
  2517.     {"listfontnames",    stdwin_listfontnames},
  2518.     {"menucreate",        stdwin_menucreate},
  2519.     {"message",        stdwin_message},
  2520. #ifdef HAVE_BITMAPS
  2521.     {"newbitmap",        stdwin_newbitmap},
  2522. #endif
  2523.     {"open",        stdwin_open},
  2524.     {"pollevent",        stdwin_pollevent},
  2525.     {"resetselection",    stdwin_resetselection},
  2526.     {"rotatecutbuffers",    stdwin_rotatecutbuffers},
  2527.     {"setcutbuffer",    stdwin_setcutbuffer},
  2528.     {"setdefscrollbars",    stdwin_setdefscrollbars},
  2529.     {"setdefwinpos",    stdwin_setdefwinpos},
  2530.     {"setdefwinsize",    stdwin_setdefwinsize},
  2531.     
  2532.     /* Text measuring methods borrow code from drawing objects: */
  2533.     {"baseline",        (PyCFunction)drawing_baseline},
  2534.     {"lineheight",        (PyCFunction)drawing_lineheight},
  2535.     {"textbreak",        (PyCFunction)drawing_textbreak},
  2536.     {"textwidth",        (PyCFunction)drawing_textwidth},
  2537.  
  2538.     /* Same for font setting methods: */
  2539.     {"setfont",        (PyCFunction)drawing_setfont},
  2540.  
  2541.     /* Same for color setting/getting methods: */
  2542.     {"getbgcolor",        (PyCFunction)drawing_getbgcolor},
  2543.     {"getfgcolor",        (PyCFunction)drawing_getfgcolor},
  2544.     {"setbgcolor",        (PyCFunction)drawing_setbgcolor},
  2545.     {"setfgcolor",        (PyCFunction)drawing_setfgcolor},
  2546.  
  2547.     {NULL,            NULL}        /* sentinel */
  2548. };
  2549.  
  2550. #ifndef macintosh
  2551. static int
  2552. checkstringlist(args, ps, pn)
  2553.     PyObject *args;
  2554.     char ***ps;
  2555.     int *pn;
  2556. {
  2557.     int i, n;
  2558.     char **s;
  2559.     if (!PyList_Check(args)) {
  2560.         PyErr_SetString(PyExc_TypeError, "list of strings expected");
  2561.         return 0;
  2562.     }
  2563.     n = PyList_Size(args);
  2564.     s = PyMem_NEW(char *, n+1);
  2565.     if (s == NULL) {
  2566.         PyErr_NoMemory();
  2567.         return 0;
  2568.     }
  2569.     for (i = 0; i < n; i++) {
  2570.         PyObject *item = PyList_GetItem(args, i);
  2571.         if (!PyString_Check(item)) {
  2572.             PyErr_SetString(PyExc_TypeError,
  2573.                     "list of strings expected");
  2574.             return 0;
  2575.         }
  2576.         s[i] = PyString_AsString(item);
  2577.     }
  2578.     s[n] = NULL; /* In case caller wants a NULL-terminated list */
  2579.     *ps = s;
  2580.     *pn = n;
  2581.     return 1;
  2582. }
  2583.  
  2584. static int
  2585. putbackstringlist(list, s, n)
  2586.     PyObject *list;
  2587.     char **s;
  2588.     int n;
  2589. {
  2590.     int oldsize = PyList_Size(list);
  2591.     PyObject *newlist;
  2592.     int i;
  2593.     if (n == oldsize)
  2594.         return 1;
  2595.     newlist = PyList_New(n);
  2596.     for (i = 0; i < n && newlist != NULL; i++) {
  2597.         PyObject *item = PyString_FromString(s[i]);
  2598.         if (item == NULL) {
  2599.             Py_DECREF(newlist);
  2600.             newlist = NULL;
  2601.         }
  2602.         else
  2603.             PyList_SetItem(newlist, i, item);
  2604.     }
  2605.     if (newlist == NULL)
  2606.         return 0;
  2607.     (*list->ob_type->tp_as_sequence->sq_ass_slice)
  2608.         (list, 0, oldsize, newlist);
  2609.     Py_DECREF(newlist);
  2610.     return 1;
  2611. }
  2612. #endif /* macintosh */
  2613.  
  2614. DL_EXPORT(void)
  2615. initstdwin()
  2616. {
  2617.     PyObject *m, *d;
  2618.     static int inited = 0;
  2619.  
  2620.     if (!inited) {
  2621. #ifdef macintosh
  2622.         winit();
  2623.         PyMac_DoYieldEnabled = 0;
  2624. #else
  2625.         char buf[1000];
  2626.         int argc = 0;
  2627.         char **argv = NULL;
  2628.         PyObject *sys_argv = PySys_GetObject("argv");
  2629.         if (sys_argv != NULL) {
  2630.             if (!checkstringlist(sys_argv, &argv, &argc))
  2631.                 PyErr_Clear();
  2632.         }
  2633.         if (argc > 0) {
  2634.             /* If argv[0] has a ".py" suffix, remove the suffix */
  2635.             char *p = strrchr(argv[0], '.');
  2636.             if (p != NULL && strcmp(p, ".py") == 0) {
  2637.                 int n = p - argv[0];
  2638.                 if (n >= sizeof(buf))
  2639.                     n = sizeof(buf)-1;
  2640.                 strncpy(buf, argv[0], n);
  2641.                 buf[n] = '\0';
  2642.                 argv[0] = buf;
  2643.             }
  2644.         }
  2645.         winitargs(&argc, &argv);
  2646.         if (argv != NULL) {
  2647.             if (!putbackstringlist(sys_argv, argv, argc))
  2648.                 PyErr_Clear();
  2649.         }
  2650. #endif
  2651.         inited = 1;
  2652.     }
  2653.     m = Py_InitModule("stdwin", stdwin_methods);
  2654.     d = PyModule_GetDict(m);
  2655.     
  2656.     /* Initialize stdwin.error exception */
  2657.     StdwinError = PyErr_NewException("stdwin.error", NULL, NULL);
  2658.     if (StdwinError == NULL ||
  2659.         PyDict_SetItemString(d, "error", StdwinError) != 0)
  2660.         return;
  2661. #ifdef WITH_THREAD
  2662.     StdwinLock = PyThread_allocate_lock();
  2663. #endif
  2664. }
  2665.