home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Python 1.4 / Python 1.4 source / Modules / stdwinmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-28  |  50.9 KB  |  2,659 lines  |  [TEXT/CWIE]

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