At the release of 1.0.1.
[python/dscho.git] / Modules / stdwinmodule.c
blobfc81cffded6f40f0f6047928eef5004e211b3ffa
1 /***********************************************************
2 Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
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 not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Stdwin module */
27 /* Stdwin itself is a module, not a separate object type.
28 Object types defined here:
29 wp: a window
30 dp: a drawing structure (only one can exist at a time)
31 mp: a menu
32 tp: a textedit block
33 bp: a bitmap
36 /* Rules for translating C stdwin function calls into Python stwin:
37 - All names drop their initial letter 'w'
38 - Functions with a window as first parameter are methods of window objects
39 - There is no equivalent for wclose(); just delete the window object
40 (all references to it!) (XXX maybe this is a bad idea)
41 - w.begindrawing() returns a drawing object
42 - There is no equivalent for wenddrawing(win); just delete the drawing
43 object (all references to it!) (XXX maybe this is a bad idea)
44 - Functions that may only be used inside wbegindrawing / wendddrawing
45 are methods of the drawing object; this includes the text measurement
46 functions (which however have doubles as module functions).
47 - Methods of the drawing object drop an initial 'draw' from their name
48 if they have it, e.g., wdrawline() --> d.line()
49 - The obvious type conversions: int --> intobject; string --> stringobject
50 - A text parameter followed by a length parameter is only a text (string)
51 parameter in Python
52 - A point or other pair of horizontal and vertical coordinates is always
53 a pair of integers in Python
54 - Two points forming a rectangle or endpoints of a line segment are a
55 pair of points in Python
56 - The arguments to d.elarc() are three points.
57 - The functions wgetclip() and wsetclip() are translated into
58 stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
59 a bad word for what these functions do (clipping has a different
60 meaning in the drawing world), while cutbuffer is standard X jargon.
61 XXX This must change again in the light of changes to stdwin!
62 - For textedit, similar rules hold, but they are less strict.
63 XXX more?
66 #include "allobjects.h"
67 #include "modsupport.h"
68 #include "ceval.h"
69 #include "sysmodule.h"
71 #ifdef macintosh
72 #include ":::stdwin:H:stdwin.h"
73 #else /* !macintosh */
74 #include "stdwin.h"
75 #define HAVE_BITMAPS
76 #endif /* !macintosh */
78 #ifdef USE_THREAD
80 #include "thread.h"
82 static type_lock StdwinLock; /* Lock held when interpreter not locked */
84 #define BGN_STDWIN BGN_SAVE acquire_lock(StdwinLock, 1);
85 #define RET_STDWIN release_lock(StdwinLock); RET_SAVE
86 #define END_STDWIN release_lock(StdwinLock); END_SAVE
88 #else
90 #define BGN_STDWIN BGN_SAVE
91 #define RET_STDWIN RET_SAVE
92 #define END_STDWIN END_SAVE
94 #endif
96 #define getpointarg(v, a) getargs(v, "(ii)", a, (a)+1)
97 #define get3pointarg(v, a) getargs(v, "((ii)(ii)(ii))", \
98 a, a+1, a+2, a+3, a+4, a+5)
99 #define getrectarg(v, a) getargs(v, "((ii)(ii))", a, a+1, a+2, a+3)
100 #define getrectintarg(v, a) getargs(v, "(((ii)(ii))i)", a, a+1, a+2, a+3, a+4)
101 #define getpointintarg(v, a) getargs(v, "((ii)i)", a, a+1, a+2)
102 #define getrectpointarg(v, a) getargs(v, "(((ii)(ii))(ii))", \
103 a, a+1, a+2, a+3, a+4, a+5)
105 static object *StdwinError; /* Exception stdwin.error */
107 /* Window and menu object types declared here because of forward references */
109 typedef struct {
110 OB_HEAD
111 object *w_title;
112 WINDOW *w_win;
113 object *w_attr; /* Attributes dictionary */
114 } windowobject;
116 extern typeobject Windowtype; /* Really static, forward */
118 #define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
120 typedef struct {
121 OB_HEAD
122 MENU *m_menu;
123 int m_id;
124 object *m_attr; /* Attributes dictionary */
125 } menuobject;
127 extern typeobject Menutype; /* Really static, forward */
129 #define is_menuobject(mp) ((mp)->ob_type == &Menutype)
131 typedef struct {
132 OB_HEAD
133 BITMAP *b_bitmap;
134 object *b_attr; /* Attributes dictionary */
135 } bitmapobject;
137 extern typeobject Bitmaptype; /* Really static, forward */
139 #define is_bitmapobject(mp) ((mp)->ob_type == &Bitmaptype)
142 /* Strongly stdwin-specific argument handlers */
144 static int
145 getmenudetail(v, ep)
146 object *v;
147 EVENT *ep;
149 menuobject *mp;
150 if (!getargs(v, "(Oi)", &mp, &ep->u.m.item))
151 return 0;
152 if (!is_menuobject(mp))
153 return err_badarg();
154 ep->u.m.id = mp->m_id;
155 return 1;
158 static int
159 geteventarg(v, ep)
160 object *v;
161 EVENT *ep;
163 object *wp, *detail;
164 int a[4];
165 if (!getargs(v, "(iOO)", &ep->type, &wp, &detail))
166 return 0;
167 if (is_windowobject(wp))
168 ep->window = ((windowobject *)wp) -> w_win;
169 else if (wp == None)
170 ep->window = NULL;
171 else
172 return err_badarg();
173 switch (ep->type) {
174 case WE_CHAR: {
175 char c;
176 if (!getargs(detail, "c", &c))
177 return 0;
178 ep->u.character = c;
179 return 1;
181 case WE_COMMAND:
182 return getintarg(detail, &ep->u.command);
183 case WE_DRAW:
184 if (!getrectarg(detail, a))
185 return 0;
186 ep->u.area.left = a[0];
187 ep->u.area.top = a[1];
188 ep->u.area.right = a[2];
189 ep->u.area.bottom = a[3];
190 return 1;
191 case WE_MOUSE_DOWN:
192 case WE_MOUSE_UP:
193 case WE_MOUSE_MOVE:
194 return getargs(detail, "((ii)iii)",
195 &ep->u.where.h, &ep->u.where.v,
196 &ep->u.where.clicks,
197 &ep->u.where.button,
198 &ep->u.where.mask);
199 case WE_MENU:
200 return getmenudetail(detail, ep);
201 case WE_KEY:
202 return getargs(detail, "(ii)",
203 &ep->u.key.code, &ep->u.key.mask);
204 default:
205 return 1;
210 /* Return construction tools */
212 static object *
213 makepoint(a, b)
214 int a, b;
216 return mkvalue("(ii)", a, b);
219 static object *
220 makerect(a, b, c, d)
221 int a, b, c, d;
223 return mkvalue("((ii)(ii))", a, b, c, d);
227 /* Drawing objects */
229 typedef struct {
230 OB_HEAD
231 windowobject *d_ref;
232 } drawingobject;
234 static drawingobject *Drawing; /* Set to current drawing object, or NULL */
236 /* Drawing methods */
238 static object *
239 drawing_close(dp)
240 drawingobject *dp;
242 if (dp->d_ref != NULL) {
243 wenddrawing(dp->d_ref->w_win);
244 Drawing = NULL;
245 DECREF(dp->d_ref);
246 dp->d_ref = NULL;
248 INCREF(None);
249 return None;
252 static void
253 drawing_dealloc(dp)
254 drawingobject *dp;
256 if (dp->d_ref != NULL) {
257 wenddrawing(dp->d_ref->w_win);
258 Drawing = NULL;
259 DECREF(dp->d_ref);
260 dp->d_ref = NULL;
262 free((char *)dp);
265 static object *
266 drawing_generic(dp, args, func)
267 drawingobject *dp;
268 object *args;
269 void (*func) FPROTO((int, int, int, int));
271 int a[4];
272 if (!getrectarg(args, a))
273 return NULL;
274 (*func)(a[0], a[1], a[2], a[3]);
275 INCREF(None);
276 return None;
279 static object *
280 drawing_line(dp, args)
281 drawingobject *dp;
282 object *args;
284 return drawing_generic(dp, args, wdrawline);
287 static object *
288 drawing_xorline(dp, args)
289 drawingobject *dp;
290 object *args;
292 return drawing_generic(dp, args, wxorline);
295 static object *
296 drawing_circle(dp, args)
297 drawingobject *dp;
298 object *args;
300 int a[3];
301 if (!getpointintarg(args, a))
302 return NULL;
303 wdrawcircle(a[0], a[1], a[2]);
304 INCREF(None);
305 return None;
308 static object *
309 drawing_fillcircle(dp, args)
310 drawingobject *dp;
311 object *args;
313 int a[3];
314 if (!getpointintarg(args, a))
315 return NULL;
316 wfillcircle(a[0], a[1], a[2]);
317 INCREF(None);
318 return None;
321 static object *
322 drawing_xorcircle(dp, args)
323 drawingobject *dp;
324 object *args;
326 int a[3];
327 if (!getpointintarg(args, a))
328 return NULL;
329 wxorcircle(a[0], a[1], a[2]);
330 INCREF(None);
331 return None;
334 static object *
335 drawing_elarc(dp, args)
336 drawingobject *dp;
337 object *args;
339 int a[6];
340 if (!get3pointarg(args, a))
341 return NULL;
342 wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
343 INCREF(None);
344 return None;
347 static object *
348 drawing_fillelarc(dp, args)
349 drawingobject *dp;
350 object *args;
352 int a[6];
353 if (!get3pointarg(args, a))
354 return NULL;
355 wfillelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
356 INCREF(None);
357 return None;
360 static object *
361 drawing_xorelarc(dp, args)
362 drawingobject *dp;
363 object *args;
365 int a[6];
366 if (!get3pointarg(args, a))
367 return NULL;
368 wxorelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
369 INCREF(None);
370 return None;
373 static object *
374 drawing_box(dp, args)
375 drawingobject *dp;
376 object *args;
378 return drawing_generic(dp, args, wdrawbox);
381 static object *
382 drawing_erase(dp, args)
383 drawingobject *dp;
384 object *args;
386 return drawing_generic(dp, args, werase);
389 static object *
390 drawing_paint(dp, args)
391 drawingobject *dp;
392 object *args;
394 return drawing_generic(dp, args, wpaint);
397 static object *
398 drawing_invert(dp, args)
399 drawingobject *dp;
400 object *args;
402 return drawing_generic(dp, args, winvert);
405 static POINT *
406 getpointsarray(v, psize)
407 object *v;
408 int *psize;
410 int n = -1;
411 object * (*getitem) PROTO((object *, int));
412 int i;
413 POINT *points;
415 if (v == NULL)
417 else if (is_listobject(v)) {
418 n = getlistsize(v);
419 getitem = getlistitem;
421 else if (is_tupleobject(v)) {
422 n = gettuplesize(v);
423 getitem = gettupleitem;
426 if (n <= 0) {
427 (void) err_badarg();
428 return NULL;
431 points = NEW(POINT, n);
432 if (points == NULL) {
433 (void) err_nomem();
434 return NULL;
437 for (i = 0; i < n; i++) {
438 object *w = (*getitem)(v, i);
439 int a[2];
440 if (!getpointarg(w, a)) {
441 DEL(points);
442 return NULL;
444 points[i].h = a[0];
445 points[i].v = a[1];
448 *psize = n;
449 return points;
452 static object *
453 drawing_poly(dp, args)
454 drawingobject *dp;
455 object *args;
457 int n;
458 POINT *points = getpointsarray(args, &n);
459 if (points == NULL)
460 return NULL;
461 wdrawpoly(n, points);
462 DEL(points);
463 INCREF(None);
464 return None;
467 static object *
468 drawing_fillpoly(dp, args)
469 drawingobject *dp;
470 object *args;
472 int n;
473 POINT *points = getpointsarray(args, &n);
474 if (points == NULL)
475 return NULL;
476 wfillpoly(n, points);
477 DEL(points);
478 INCREF(None);
479 return None;
482 static object *
483 drawing_xorpoly(dp, args)
484 drawingobject *dp;
485 object *args;
487 int n;
488 POINT *points = getpointsarray(args, &n);
489 if (points == NULL)
490 return NULL;
491 wxorpoly(n, points);
492 DEL(points);
493 INCREF(None);
494 return None;
497 static object *
498 drawing_cliprect(dp, args)
499 drawingobject *dp;
500 object *args;
502 return drawing_generic(dp, args, wcliprect);
505 static object *
506 drawing_noclip(dp, args)
507 drawingobject *dp;
508 object *args;
510 if (!getnoarg(args))
511 return NULL;
512 wnoclip();
513 INCREF(None);
514 return None;
517 static object *
518 drawing_shade(dp, args)
519 drawingobject *dp;
520 object *args;
522 int a[5];
523 if (!getrectintarg(args, a))
524 return NULL;
525 wshade(a[0], a[1], a[2], a[3], a[4]);
526 INCREF(None);
527 return None;
530 static object *
531 drawing_text(dp, args)
532 drawingobject *dp;
533 object *args;
535 int h, v, size;
536 char *text;
537 if (!getargs(args, "((ii)s#)", &h, &v, &text, &size))
538 return NULL;
539 wdrawtext(h, v, text, size);
540 INCREF(None);
541 return None;
544 /* The following four are also used as stdwin functions */
546 static object *
547 drawing_lineheight(dp, args)
548 drawingobject *dp;
549 object *args;
551 if (!getnoarg(args))
552 return NULL;
553 return newintobject((long)wlineheight());
556 static object *
557 drawing_baseline(dp, args)
558 drawingobject *dp;
559 object *args;
561 if (!getnoarg(args))
562 return NULL;
563 return newintobject((long)wbaseline());
566 static object *
567 drawing_textwidth(dp, args)
568 drawingobject *dp;
569 object *args;
571 char *text;
572 int size;
573 if (!getargs(args, "s#", &text, &size))
574 return NULL;
575 return newintobject((long)wtextwidth(text, size));
578 static object *
579 drawing_textbreak(dp, args)
580 drawingobject *dp;
581 object *args;
583 char *text;
584 int size, width;
585 if (!getargs(args, "(s#i)", &text, &size, &width))
586 return NULL;
587 return newintobject((long)wtextbreak(text, size, width));
590 static object *
591 drawing_setfont(self, args)
592 drawingobject *self;
593 object *args;
595 char *font;
596 char style = '\0';
597 int size = 0;
598 if (args == NULL || !is_tupleobject(args)) {
599 if (!getargs(args, "z", &font))
600 return NULL;
602 else {
603 int n = gettuplesize(args);
604 if (n == 2) {
605 if (!getargs(args, "(zi)", &font, &size))
606 return NULL;
608 else if (!getargs(args, "(zic)", &font, &size, &style)) {
609 err_clear();
610 if (!getargs(args, "(zci)", &font, &style, &size))
611 return NULL;
614 if (font != NULL) {
615 if (!wsetfont(font)) {
616 err_setstr(StdwinError, "font not found");
617 return NULL;
620 if (size != 0)
621 wsetsize(size);
622 switch (style) {
623 case 'b':
624 wsetbold();
625 break;
626 case 'i':
627 wsetitalic();
628 break;
629 case 'o':
630 wsetbolditalic();
631 break;
632 case 'u':
633 wsetunderline();
634 break;
635 case 'p':
636 wsetplain();
637 break;
639 INCREF(None);
640 return None;
643 static object *
644 drawing_getbgcolor(self, args)
645 object *self;
646 object *args;
648 if (!getnoarg(args))
649 return NULL;
650 return newintobject((long)wgetbgcolor());
653 static object *
654 drawing_getfgcolor(self, args)
655 object *self;
656 object *args;
658 if (!getnoarg(args))
659 return NULL;
660 return newintobject((long)wgetfgcolor());
663 static object *
664 drawing_setbgcolor(self, args)
665 object *self;
666 object *args;
668 long color;
669 if (!getlongarg(args, &color))
670 return NULL;
671 wsetbgcolor((COLOR)color);
672 INCREF(None);
673 return None;
676 static object *
677 drawing_setfgcolor(self, args)
678 object *self;
679 object *args;
681 long color;
682 if (!getlongarg(args, &color))
683 return NULL;
684 wsetfgcolor((COLOR)color);
685 INCREF(None);
686 return None;
689 #ifdef HAVE_BITMAPS
691 static object *
692 drawing_bitmap(self, args)
693 object *self;
694 object *args;
696 int h, v;
697 object *bp;
698 object *mask = NULL;
699 if (!getargs(args, "((ii)O)", &h, &v, &bp)) {
700 err_clear();
701 if (!getargs(args, "((ii)OO)", &h, &v, &bp, &mask))
702 return NULL;
703 if (mask == None)
704 mask = NULL;
705 else if (!is_bitmapobject(mask)) {
706 err_badarg();
707 return NULL;
710 if (!is_bitmapobject(bp)) {
711 err_badarg();
712 return NULL;
714 if (((bitmapobject *)bp)->b_bitmap == NULL ||
715 mask != NULL && ((bitmapobject *)mask)->b_bitmap == NULL) {
716 err_setstr(StdwinError, "bitmap object already close");
717 return NULL;
719 if (mask == NULL)
720 wdrawbitmap(h, v, ((bitmapobject *)bp)->b_bitmap, ALLBITS);
721 else
722 wdrawbitmap(h, v,
723 ((bitmapobject *)bp)->b_bitmap,
724 ((bitmapobject *)bp)->b_bitmap);
725 INCREF(None);
726 return None;
729 #endif /* HAVE_BITMAPS */
731 static struct methodlist drawing_methods[] = {
732 #ifdef HAVE_BITMAPS
733 {"bitmap", drawing_bitmap},
734 #endif
735 {"box", drawing_box},
736 {"circle", drawing_circle},
737 {"cliprect", drawing_cliprect},
738 {"close", drawing_close},
739 {"elarc", drawing_elarc},
740 {"enddrawing", drawing_close},
741 {"erase", drawing_erase},
742 {"fillcircle", drawing_fillcircle},
743 {"fillelarc", drawing_fillelarc},
744 {"fillpoly", drawing_fillpoly},
745 {"invert", drawing_invert},
746 {"line", drawing_line},
747 {"noclip", drawing_noclip},
748 {"paint", drawing_paint},
749 {"poly", drawing_poly},
750 {"shade", drawing_shade},
751 {"text", drawing_text},
752 {"xorcircle", drawing_xorcircle},
753 {"xorelarc", drawing_xorelarc},
754 {"xorline", drawing_xorline},
755 {"xorpoly", drawing_xorpoly},
757 /* Text measuring methods: */
758 {"baseline", drawing_baseline},
759 {"lineheight", drawing_lineheight},
760 {"textbreak", drawing_textbreak},
761 {"textwidth", drawing_textwidth},
763 /* Font setting methods: */
764 {"setfont", drawing_setfont},
766 /* Color methods: */
767 {"getbgcolor", drawing_getbgcolor},
768 {"getfgcolor", drawing_getfgcolor},
769 {"setbgcolor", drawing_setbgcolor},
770 {"setfgcolor", drawing_setfgcolor},
772 {NULL, NULL} /* sentinel */
775 static object *
776 drawing_getattr(dp, name)
777 drawingobject *dp;
778 char *name;
780 if (dp->d_ref == NULL) {
781 err_setstr(StdwinError, "drawing object already closed");
782 return NULL;
784 return findmethod(drawing_methods, (object *)dp, name);
787 typeobject Drawingtype = {
788 OB_HEAD_INIT(&Typetype)
789 0, /*ob_size*/
790 "drawing", /*tp_name*/
791 sizeof(drawingobject), /*tp_size*/
792 0, /*tp_itemsize*/
793 /* methods */
794 drawing_dealloc, /*tp_dealloc*/
795 0, /*tp_print*/
796 drawing_getattr, /*tp_getattr*/
797 0, /*tp_setattr*/
798 0, /*tp_compare*/
799 0, /*tp_repr*/
803 /* Text(edit) objects */
805 typedef struct {
806 OB_HEAD
807 TEXTEDIT *t_text;
808 windowobject *t_ref;
809 object *t_attr; /* Attributes dictionary */
810 } textobject;
812 extern typeobject Texttype; /* Really static, forward */
814 static textobject *
815 newtextobject(wp, left, top, right, bottom)
816 windowobject *wp;
817 int left, top, right, bottom;
819 textobject *tp;
820 tp = NEWOBJ(textobject, &Texttype);
821 if (tp == NULL)
822 return NULL;
823 tp->t_attr = NULL;
824 INCREF(wp);
825 tp->t_ref = wp;
826 tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
827 if (tp->t_text == NULL) {
828 DECREF(tp);
829 return (textobject *) err_nomem();
831 return tp;
834 /* Text(edit) methods */
836 static void
837 text_dealloc(tp)
838 textobject *tp;
840 if (tp->t_text != NULL)
841 tefree(tp->t_text);
842 XDECREF(tp->t_attr);
843 XDECREF(tp->t_ref);
844 DEL(tp);
847 static object *
848 text_close(tp, args)
849 textobject *tp;
850 object *args;
852 if (tp->t_text != NULL) {
853 tefree(tp->t_text);
854 tp->t_text = NULL;
856 if (tp->t_attr != NULL) {
857 DECREF(tp->t_attr);
858 tp->t_attr = NULL;
860 if (tp->t_ref != NULL) {
861 DECREF(tp->t_ref);
862 tp->t_ref = NULL;
864 INCREF(None);
865 return None;
868 static object *
869 text_arrow(self, args)
870 textobject *self;
871 object *args;
873 int code;
874 if (!getintarg(args, &code))
875 return NULL;
876 tearrow(self->t_text, code);
877 INCREF(None);
878 return None;
881 static object *
882 text_draw(self, args)
883 textobject *self;
884 object *args;
886 register TEXTEDIT *tp = self->t_text;
887 int a[4];
888 int left, top, right, bottom;
889 if (!getrectarg(args, a))
890 return NULL;
891 if (Drawing != NULL) {
892 err_setstr(StdwinError, "already drawing");
893 return NULL;
895 /* Clip to text area and ignore if area is empty */
896 left = tegetleft(tp);
897 top = tegettop(tp);
898 right = tegetright(tp);
899 bottom = tegetbottom(tp);
900 if (a[0] < left) a[0] = left;
901 if (a[1] < top) a[1] = top;
902 if (a[2] > right) a[2] = right;
903 if (a[3] > bottom) a[3] = bottom;
904 if (a[0] < a[2] && a[1] < a[3]) {
905 wbegindrawing(self->t_ref->w_win);
906 tedrawnew(tp, a[0], a[1], a[2], a[3]);
907 wenddrawing(self->t_ref->w_win);
909 INCREF(None);
910 return None;
913 static object *
914 text_event(self, args)
915 textobject *self;
916 object *args;
918 register TEXTEDIT *tp = self->t_text;
919 EVENT e;
920 if (!geteventarg(args, &e))
921 return NULL;
922 if (e.type == WE_MOUSE_DOWN) {
923 /* Cheat at the margins */
924 int width, height;
925 wgetdocsize(e.window, &width, &height);
926 if (e.u.where.h < 0 && tegetleft(tp) == 0)
927 e.u.where.h = 0;
928 else if (e.u.where.h > width && tegetright(tp) == width)
929 e.u.where.h = width;
930 if (e.u.where.v < 0 && tegettop(tp) == 0)
931 e.u.where.v = 0;
932 else if (e.u.where.v > height && tegetright(tp) == height)
933 e.u.where.v = height;
935 return newintobject((long) teevent(tp, &e));
938 static object *
939 text_getfocus(self, args)
940 textobject *self;
941 object *args;
943 if (!getnoarg(args))
944 return NULL;
945 return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
948 static object *
949 text_getfocustext(self, args)
950 textobject *self;
951 object *args;
953 int f1, f2;
954 char *text;
955 if (!getnoarg(args))
956 return NULL;
957 f1 = tegetfoc1(self->t_text);
958 f2 = tegetfoc2(self->t_text);
959 text = tegettext(self->t_text);
960 return newsizedstringobject(text + f1, f2-f1);
963 static object *
964 text_getrect(self, args)
965 textobject *self;
966 object *args;
968 if (!getnoarg(args))
969 return NULL;
970 return makerect(tegetleft(self->t_text),
971 tegettop(self->t_text),
972 tegetright(self->t_text),
973 tegetbottom(self->t_text));
976 static object *
977 text_gettext(self, args)
978 textobject *self;
979 object *args;
981 if (!getnoarg(args))
982 return NULL;
983 return newsizedstringobject(tegettext(self->t_text),
984 tegetlen(self->t_text));
987 static object *
988 text_move(self, args)
989 textobject *self;
990 object *args;
992 int a[4];
993 if (!getrectarg(args, a))
994 return NULL;
995 temovenew(self->t_text, a[0], a[1], a[2], a[3]);
996 INCREF(None);
997 return None;
1000 static object *
1001 text_replace(self, args)
1002 textobject *self;
1003 object *args;
1005 char *text;
1006 if (!getstrarg(args, &text))
1007 return NULL;
1008 tereplace(self->t_text, text);
1009 INCREF(None);
1010 return None;
1013 static object *
1014 text_setactive(self, args)
1015 textobject *self;
1016 object *args;
1018 int flag;
1019 if (!getintarg(args, &flag))
1020 return NULL;
1021 tesetactive(self->t_text, flag);
1022 INCREF(None);
1023 return None;
1026 static object *
1027 text_setfocus(self, args)
1028 textobject *self;
1029 object *args;
1031 int a[2];
1032 if (!getpointarg(args, a))
1033 return NULL;
1034 tesetfocus(self->t_text, a[0], a[1]);
1035 INCREF(None);
1036 return None;
1039 static object *
1040 text_settext(self, args)
1041 textobject *self;
1042 object *args;
1044 char *text;
1045 char *buf;
1046 int size;
1047 if (!getargs(args, "s#", &text, &size))
1048 return NULL;
1049 if ((buf = NEW(char, size)) == NULL) {
1050 return err_nomem();
1052 memcpy(buf, text, size);
1053 tesetbuf(self->t_text, buf, size); /* Becomes owner of buffer */
1054 INCREF(None);
1055 return None;
1058 static object *
1059 text_setview(self, args)
1060 textobject *self;
1061 object *args;
1063 int a[4];
1064 if (args == None)
1065 tenoview(self->t_text);
1066 else {
1067 if (!getrectarg(args, a))
1068 return NULL;
1069 tesetview(self->t_text, a[0], a[1], a[2], a[3]);
1071 INCREF(None);
1072 return None;
1075 static struct methodlist text_methods[] = {
1076 {"arrow", text_arrow},
1077 {"close", text_close},
1078 {"draw", text_draw},
1079 {"event", text_event},
1080 {"getfocus", text_getfocus},
1081 {"getfocustext",text_getfocustext},
1082 {"getrect", text_getrect},
1083 {"gettext", text_gettext},
1084 {"move", text_move},
1085 {"replace", text_replace},
1086 {"setactive", text_setactive},
1087 {"setfocus", text_setfocus},
1088 {"settext", text_settext},
1089 {"setview", text_setview},
1090 {NULL, NULL} /* sentinel */
1093 static object *
1094 text_getattr(tp, name)
1095 textobject *tp;
1096 char *name;
1098 object *v = NULL;
1099 if (tp->t_ref == NULL) {
1100 err_setstr(StdwinError, "text object already closed");
1101 return NULL;
1103 if (strcmp(name, "__dict__") == 0) {
1104 v = tp->t_attr;
1105 if (v == NULL)
1106 v = None;
1108 else if (tp->t_attr != NULL) {
1109 v = dictlookup(tp->t_attr, name);
1111 if (v != NULL) {
1112 INCREF(v);
1113 return v;
1115 return findmethod(text_methods, (object *)tp, name);
1118 static int
1119 text_setattr(tp, name, v)
1120 textobject *tp;
1121 char *name;
1122 object *v;
1124 if (tp->t_attr == NULL) {
1125 tp->t_attr = newdictobject();
1126 if (tp->t_attr == NULL)
1127 return -1;
1129 if (v == NULL) {
1130 int rv = dictremove(tp->t_attr, name);
1131 if (rv < 0)
1132 err_setstr(AttributeError,
1133 "delete non-existing text object attribute");
1134 return rv;
1136 else
1137 return dictinsert(tp->t_attr, name, v);
1140 typeobject Texttype = {
1141 OB_HEAD_INIT(&Typetype)
1142 0, /*ob_size*/
1143 "textedit", /*tp_name*/
1144 sizeof(textobject), /*tp_size*/
1145 0, /*tp_itemsize*/
1146 /* methods */
1147 text_dealloc, /*tp_dealloc*/
1148 0, /*tp_print*/
1149 text_getattr, /*tp_getattr*/
1150 text_setattr, /*tp_setattr*/
1151 0, /*tp_compare*/
1152 0, /*tp_repr*/
1156 /* Menu objects */
1158 #define IDOFFSET 10 /* Menu IDs we use start here */
1159 #define MAXNMENU 200 /* Max #menus we allow */
1160 static menuobject *menulist[MAXNMENU];
1162 static menuobject *newmenuobject PROTO((char *));
1163 static menuobject *
1164 newmenuobject(title)
1165 char *title;
1167 int id;
1168 MENU *menu;
1169 menuobject *mp;
1170 for (id = 0; id < MAXNMENU; id++) {
1171 if (menulist[id] == NULL)
1172 break;
1174 if (id >= MAXNMENU) {
1175 err_setstr(StdwinError, "creating too many menus");
1176 return NULL;
1178 menu = wmenucreate(id + IDOFFSET, title);
1179 if (menu == NULL)
1180 return (menuobject *) err_nomem();
1181 mp = NEWOBJ(menuobject, &Menutype);
1182 if (mp != NULL) {
1183 mp->m_menu = menu;
1184 mp->m_id = id + IDOFFSET;
1185 mp->m_attr = NULL;
1186 menulist[id] = mp;
1188 else
1189 wmenudelete(menu);
1190 return mp;
1193 /* Menu methods */
1195 static void
1196 menu_dealloc(mp)
1197 menuobject *mp;
1200 int id = mp->m_id - IDOFFSET;
1201 if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
1202 menulist[id] = NULL;
1204 if (mp->m_menu != NULL)
1205 wmenudelete(mp->m_menu);
1206 XDECREF(mp->m_attr);
1207 DEL(mp);
1210 static object *
1211 menu_close(mp, args)
1212 menuobject *mp;
1213 object *args;
1215 int id = mp->m_id - IDOFFSET;
1216 if (id >= 0 && id < MAXNMENU && menulist[id] == mp) {
1217 menulist[id] = NULL;
1219 mp->m_id = -1;
1220 if (mp->m_menu != NULL)
1221 wmenudelete(mp->m_menu);
1222 mp->m_menu = NULL;
1223 XDECREF(mp->m_attr);
1224 mp->m_attr = NULL;
1225 INCREF(None);
1226 return None;
1229 static object *
1230 menu_additem(self, args)
1231 menuobject *self;
1232 object *args;
1234 char *text;
1235 int shortcut = -1;
1236 if (is_tupleobject(args)) {
1237 char c;
1238 if (!getargs(args, "(sc)", &text, &c))
1239 return NULL;
1240 shortcut = c;
1242 else if (!getstrarg(args, &text))
1243 return NULL;
1244 wmenuadditem(self->m_menu, text, shortcut);
1245 INCREF(None);
1246 return None;
1249 static object *
1250 menu_setitem(self, args)
1251 menuobject *self;
1252 object *args;
1254 int index;
1255 char *text;
1256 if (!getargs(args, "(is)", &index, &text))
1257 return NULL;
1258 wmenusetitem(self->m_menu, index, text);
1259 INCREF(None);
1260 return None;
1263 static object *
1264 menu_enable(self, args)
1265 menuobject *self;
1266 object *args;
1268 int index;
1269 int flag;
1270 if (!getargs(args, "(ii)", &index, &flag))
1271 return NULL;
1272 wmenuenable(self->m_menu, index, flag);
1273 INCREF(None);
1274 return None;
1277 static object *
1278 menu_check(self, args)
1279 menuobject *self;
1280 object *args;
1282 int index;
1283 int flag;
1284 if (!getargs(args, "(ii)", &index, &flag))
1285 return NULL;
1286 wmenucheck(self->m_menu, index, flag);
1287 INCREF(None);
1288 return None;
1291 static struct methodlist menu_methods[] = {
1292 {"additem", menu_additem},
1293 {"setitem", menu_setitem},
1294 {"enable", menu_enable},
1295 {"check", menu_check},
1296 {"close", menu_close},
1297 {NULL, NULL} /* sentinel */
1300 static object *
1301 menu_getattr(mp, name)
1302 menuobject *mp;
1303 char *name;
1305 object *v = NULL;
1306 if (mp->m_menu == NULL) {
1307 err_setstr(StdwinError, "menu object already closed");
1308 return NULL;
1310 if (strcmp(name, "__dict__") == 0) {
1311 v = mp->m_attr;
1312 if (v == NULL)
1313 v = None;
1315 else if (mp->m_attr != NULL) {
1316 v = dictlookup(mp->m_attr, name);
1318 if (v != NULL) {
1319 INCREF(v);
1320 return v;
1322 return findmethod(menu_methods, (object *)mp, name);
1325 static int
1326 menu_setattr(mp, name, v)
1327 menuobject *mp;
1328 char *name;
1329 object *v;
1331 if (mp->m_attr == NULL) {
1332 mp->m_attr = newdictobject();
1333 if (mp->m_attr == NULL)
1334 return -1;
1336 if (v == NULL) {
1337 int rv = dictremove(mp->m_attr, name);
1338 if (rv < 0)
1339 err_setstr(AttributeError,
1340 "delete non-existing menu object attribute");
1341 return rv;
1343 else
1344 return dictinsert(mp->m_attr, name, v);
1347 typeobject Menutype = {
1348 OB_HEAD_INIT(&Typetype)
1349 0, /*ob_size*/
1350 "menu", /*tp_name*/
1351 sizeof(menuobject), /*tp_size*/
1352 0, /*tp_itemsize*/
1353 /* methods */
1354 menu_dealloc, /*tp_dealloc*/
1355 0, /*tp_print*/
1356 menu_getattr, /*tp_getattr*/
1357 menu_setattr, /*tp_setattr*/
1358 0, /*tp_compare*/
1359 0, /*tp_repr*/
1363 #ifdef HAVE_BITMAPS
1365 /* Bitmaps objects */
1367 static bitmapobject *newbitmapobject PROTO((int, int));
1368 static bitmapobject *
1369 newbitmapobject(width, height)
1370 int width, height;
1372 BITMAP *bitmap;
1373 bitmapobject *bp;
1374 bitmap = wnewbitmap(width, height);
1375 if (bitmap == NULL)
1376 return (bitmapobject *) err_nomem();
1377 bp = NEWOBJ(bitmapobject, &Bitmaptype);
1378 if (bp != NULL) {
1379 bp->b_bitmap = bitmap;
1380 bp->b_attr = NULL;
1382 else
1383 wfreebitmap(bitmap);
1384 return bp;
1387 /* Bitmap methods */
1389 static void
1390 bitmap_dealloc(bp)
1391 bitmapobject *bp;
1393 if (bp->b_bitmap != NULL)
1394 wfreebitmap(bp->b_bitmap);
1395 XDECREF(bp->b_attr);
1396 DEL(bp);
1399 static object *
1400 bitmap_close(bp, args)
1401 bitmapobject *bp;
1402 object *args;
1404 if (bp->b_bitmap != NULL)
1405 wfreebitmap(bp->b_bitmap);
1406 bp->b_bitmap = NULL;
1407 XDECREF(bp->b_attr);
1408 bp->b_attr = NULL;
1409 INCREF(None);
1410 return None;
1413 static object *
1414 bitmap_setbit(self, args)
1415 bitmapobject *self;
1416 object *args;
1418 int a[3];
1419 if (!getpointintarg(args, a))
1420 return NULL;
1421 wsetbit(self->b_bitmap, a[0], a[1], a[2]);
1422 INCREF(None);
1423 return None;
1426 static object *
1427 bitmap_getbit(self, args)
1428 bitmapobject *self;
1429 object *args;
1431 int a[2];
1432 if (!getpointarg(args, a))
1433 return NULL;
1434 return newintobject((long) wgetbit(self->b_bitmap, a[0], a[1]));
1437 static object *
1438 bitmap_getsize(self, args)
1439 bitmapobject *self;
1440 object *args;
1442 int width, height;
1443 if (!getnoarg(args))
1444 return NULL;
1445 wgetbitmapsize(self->b_bitmap, &width, &height);
1446 return mkvalue("(ii)", width, height);
1449 static struct methodlist bitmap_methods[] = {
1450 {"close", bitmap_close},
1451 {"getsize", bitmap_getsize},
1452 {"getbit", bitmap_getbit},
1453 {"setbit", bitmap_setbit},
1454 {NULL, NULL} /* sentinel */
1457 static object *
1458 bitmap_getattr(bp, name)
1459 bitmapobject *bp;
1460 char *name;
1462 object *v = NULL;
1463 if (bp->b_bitmap == NULL) {
1464 err_setstr(StdwinError, "bitmap object already closed");
1465 return NULL;
1467 if (strcmp(name, "__dict__") == 0) {
1468 v = bp->b_attr;
1469 if (v == NULL)
1470 v = None;
1472 else if (bp->b_attr != NULL) {
1473 v = dictlookup(bp->b_attr, name);
1475 if (v != NULL) {
1476 INCREF(v);
1477 return v;
1479 return findmethod(bitmap_methods, (object *)bp, name);
1482 static int
1483 bitmap_setattr(bp, name, v)
1484 bitmapobject *bp;
1485 char *name;
1486 object *v;
1488 if (bp->b_attr == NULL) {
1489 bp->b_attr = newdictobject();
1490 if (bp->b_attr == NULL)
1491 return -1;
1493 if (v == NULL) {
1494 int rv = dictremove(bp->b_attr, name);
1495 if (rv < 0)
1496 err_setstr(AttributeError,
1497 "delete non-existing bitmap object attribute");
1498 return rv;
1500 else
1501 return dictinsert(bp->b_attr, name, v);
1504 typeobject Bitmaptype = {
1505 OB_HEAD_INIT(&Typetype)
1506 0, /*ob_size*/
1507 "bitmap", /*tp_name*/
1508 sizeof(bitmapobject), /*tp_size*/
1509 0, /*tp_itemsize*/
1510 /* methods */
1511 bitmap_dealloc, /*tp_dealloc*/
1512 0, /*tp_print*/
1513 bitmap_getattr, /*tp_getattr*/
1514 bitmap_setattr, /*tp_setattr*/
1515 0, /*tp_compare*/
1516 0, /*tp_repr*/
1519 #endif /* HAVE_BITMAPS */
1522 /* Windows */
1524 #define MAXNWIN 50
1525 static windowobject *windowlist[MAXNWIN];
1527 /* Window methods */
1529 static void
1530 window_dealloc(wp)
1531 windowobject *wp;
1533 if (wp->w_win != NULL) {
1534 int tag = wgettag(wp->w_win);
1535 if (tag >= 0 && tag < MAXNWIN)
1536 windowlist[tag] = NULL;
1537 else
1538 fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
1539 tag);
1540 wclose(wp->w_win);
1542 DECREF(wp->w_title);
1543 if (wp->w_attr != NULL)
1544 DECREF(wp->w_attr);
1545 free((char *)wp);
1548 static object *
1549 window_close(wp, args)
1550 windowobject *wp;
1551 object *args;
1553 if (wp->w_win != NULL) {
1554 int tag = wgettag(wp->w_win);
1555 if (tag >= 0 && tag < MAXNWIN)
1556 windowlist[tag] = NULL;
1557 wclose(wp->w_win);
1558 wp->w_win = NULL;
1560 INCREF(None);
1561 return None;
1564 static object *
1565 window_begindrawing(wp, args)
1566 windowobject *wp;
1567 object *args;
1569 drawingobject *dp;
1570 if (!getnoarg(args))
1571 return NULL;
1572 if (Drawing != NULL) {
1573 err_setstr(StdwinError, "already drawing");
1574 return NULL;
1576 dp = NEWOBJ(drawingobject, &Drawingtype);
1577 if (dp == NULL)
1578 return NULL;
1579 Drawing = dp;
1580 INCREF(wp);
1581 dp->d_ref = wp;
1582 wbegindrawing(wp->w_win);
1583 return (object *)dp;
1586 static object *
1587 window_change(wp, args)
1588 windowobject *wp;
1589 object *args;
1591 int a[4];
1592 if (!getrectarg(args, a))
1593 return NULL;
1594 wchange(wp->w_win, a[0], a[1], a[2], a[3]);
1595 INCREF(None);
1596 return None;
1599 static object *
1600 window_gettitle(wp, args)
1601 windowobject *wp;
1602 object *args;
1604 if (!getnoarg(args))
1605 return NULL;
1606 INCREF(wp->w_title);
1607 return wp->w_title;
1610 static object *
1611 window_getwinpos(wp, args)
1612 windowobject *wp;
1613 object *args;
1615 int h, v;
1616 if (!getnoarg(args))
1617 return NULL;
1618 wgetwinpos(wp->w_win, &h, &v);
1619 return makepoint(h, v);
1622 static object *
1623 window_getwinsize(wp, args)
1624 windowobject *wp;
1625 object *args;
1627 int width, height;
1628 if (!getnoarg(args))
1629 return NULL;
1630 wgetwinsize(wp->w_win, &width, &height);
1631 return makepoint(width, height);
1634 static object *
1635 window_setwinpos(wp, args)
1636 windowobject *wp;
1637 object *args;
1639 int a[2];
1640 if (!getpointarg(args, a))
1641 return NULL;
1642 wsetwinpos(wp->w_win, a[0], a[1]);
1643 INCREF(None);
1644 return None;
1647 static object *
1648 window_setwinsize(wp, args)
1649 windowobject *wp;
1650 object *args;
1652 int a[2];
1653 if (!getpointarg(args, a))
1654 return NULL;
1655 wsetwinsize(wp->w_win, a[0], a[1]);
1656 INCREF(None);
1657 return None;
1660 static object *
1661 window_getdocsize(wp, args)
1662 windowobject *wp;
1663 object *args;
1665 int width, height;
1666 if (!getnoarg(args))
1667 return NULL;
1668 wgetdocsize(wp->w_win, &width, &height);
1669 return makepoint(width, height);
1672 static object *
1673 window_getorigin(wp, args)
1674 windowobject *wp;
1675 object *args;
1677 int width, height;
1678 if (!getnoarg(args))
1679 return NULL;
1680 wgetorigin(wp->w_win, &width, &height);
1681 return makepoint(width, height);
1684 static object *
1685 window_scroll(wp, args)
1686 windowobject *wp;
1687 object *args;
1689 int a[6];
1690 if (!getrectpointarg(args, a))
1691 return NULL;
1692 wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
1693 INCREF(None);
1694 return None;
1697 static object *
1698 window_setdocsize(wp, args)
1699 windowobject *wp;
1700 object *args;
1702 int a[2];
1703 if (!getpointarg(args, a))
1704 return NULL;
1705 wsetdocsize(wp->w_win, a[0], a[1]);
1706 INCREF(None);
1707 return None;
1710 static object *
1711 window_setorigin(wp, args)
1712 windowobject *wp;
1713 object *args;
1715 int a[2];
1716 if (!getpointarg(args, a))
1717 return NULL;
1718 wsetorigin(wp->w_win, a[0], a[1]);
1719 INCREF(None);
1720 return None;
1723 static object *
1724 window_settitle(wp, args)
1725 windowobject *wp;
1726 object *args;
1728 object *title;
1729 if (!getargs(args, "S", &title))
1730 return NULL;
1731 DECREF(wp->w_title);
1732 INCREF(title);
1733 wp->w_title = title;
1734 wsettitle(wp->w_win, getstringvalue(title));
1735 INCREF(None);
1736 return None;
1739 static object *
1740 window_show(wp, args)
1741 windowobject *wp;
1742 object *args;
1744 int a[4];
1745 if (!getrectarg(args, a))
1746 return NULL;
1747 wshow(wp->w_win, a[0], a[1], a[2], a[3]);
1748 INCREF(None);
1749 return None;
1752 static object *
1753 window_settimer(wp, args)
1754 windowobject *wp;
1755 object *args;
1757 int a;
1758 if (!getintarg(args, &a))
1759 return NULL;
1760 wsettimer(wp->w_win, a);
1761 INCREF(None);
1762 return None;
1765 static object *
1766 window_menucreate(self, args)
1767 windowobject *self;
1768 object *args;
1770 menuobject *mp;
1771 char *title;
1772 if (!getstrarg(args, &title))
1773 return NULL;
1774 wmenusetdeflocal(1);
1775 mp = newmenuobject(title);
1776 if (mp == NULL)
1777 return NULL;
1778 wmenuattach(self->w_win, mp->m_menu);
1779 return (object *)mp;
1782 static object *
1783 window_textcreate(self, args)
1784 windowobject *self;
1785 object *args;
1787 textobject *tp;
1788 int a[4];
1789 if (!getrectarg(args, a))
1790 return NULL;
1791 return (object *)
1792 newtextobject(self, a[0], a[1], a[2], a[3]);
1795 static object *
1796 window_setselection(self, args)
1797 windowobject *self;
1798 object *args;
1800 int sel, size, ok;
1801 char *text;
1802 if (!getargs(args, "(is#)", &sel, &text, &size))
1803 return NULL;
1804 ok = wsetselection(self->w_win, sel, text, size);
1805 return newintobject(ok);
1808 static object *
1809 window_setwincursor(self, args)
1810 windowobject *self;
1811 object *args;
1813 char *name;
1814 CURSOR *c;
1815 if (!getargs(args, "z", &name))
1816 return NULL;
1817 if (name == NULL)
1818 c = NULL;
1819 else {
1820 c = wfetchcursor(name);
1821 if (c == NULL) {
1822 err_setstr(StdwinError, "no such cursor");
1823 return NULL;
1826 wsetwincursor(self->w_win, c);
1827 INCREF(None);
1828 return None;
1831 static object *
1832 window_setactive(self, args)
1833 windowobject *self;
1834 object *args;
1836 if (!getnoarg(args))
1837 return NULL;
1838 wsetactive(self->w_win);
1839 INCREF(None);
1840 return None;
1843 #ifdef CWI_HACKS
1844 static object *
1845 window_getxwindowid(self, args)
1846 windowobject *self;
1847 object *args;
1849 long wid = wgetxwindowid(self->w_win);
1850 return newintobject(wid);
1852 #endif
1854 static struct methodlist window_methods[] = {
1855 {"begindrawing",window_begindrawing},
1856 {"change", window_change},
1857 {"close", window_close},
1858 {"getdocsize", window_getdocsize},
1859 {"getorigin", window_getorigin},
1860 {"gettitle", window_gettitle},
1861 {"getwinpos", window_getwinpos},
1862 {"getwinsize", window_getwinsize},
1863 {"menucreate", window_menucreate},
1864 {"scroll", window_scroll},
1865 {"setactive", window_setactive},
1866 {"setdocsize", window_setdocsize},
1867 {"setorigin", window_setorigin},
1868 {"setselection",window_setselection},
1869 {"settimer", window_settimer},
1870 {"settitle", window_settitle},
1871 {"setwincursor",window_setwincursor},
1872 {"setwinpos", window_setwinpos},
1873 {"setwinsize", window_setwinsize},
1874 {"show", window_show},
1875 {"textcreate", window_textcreate},
1876 #ifdef CWI_HACKS
1877 {"getxwindowid",window_getxwindowid},
1878 #endif
1879 {NULL, NULL} /* sentinel */
1882 static object *
1883 window_getattr(wp, name)
1884 windowobject *wp;
1885 char *name;
1887 object *v = NULL;
1888 if (wp->w_win == NULL) {
1889 err_setstr(StdwinError, "window already closed");
1890 return NULL;
1892 if (strcmp(name, "__dict__") == 0) {
1893 v = wp->w_attr;
1894 if (v == NULL)
1895 v = None;
1897 else if (wp->w_attr != NULL) {
1898 v = dictlookup(wp->w_attr, name);
1900 if (v != NULL) {
1901 INCREF(v);
1902 return v;
1904 return findmethod(window_methods, (object *)wp, name);
1907 static int
1908 window_setattr(wp, name, v)
1909 windowobject *wp;
1910 char *name;
1911 object *v;
1913 if (wp->w_attr == NULL) {
1914 wp->w_attr = newdictobject();
1915 if (wp->w_attr == NULL)
1916 return -1;
1918 if (v == NULL) {
1919 int rv = dictremove(wp->w_attr, name);
1920 if (rv < 0)
1921 err_setstr(AttributeError,
1922 "delete non-existing menu object attribute");
1923 return rv;
1925 else
1926 return dictinsert(wp->w_attr, name, v);
1929 typeobject Windowtype = {
1930 OB_HEAD_INIT(&Typetype)
1931 0, /*ob_size*/
1932 "window", /*tp_name*/
1933 sizeof(windowobject), /*tp_size*/
1934 0, /*tp_itemsize*/
1935 /* methods */
1936 window_dealloc, /*tp_dealloc*/
1937 0, /*tp_print*/
1938 window_getattr, /*tp_getattr*/
1939 window_setattr, /*tp_setattr*/
1940 0, /*tp_compare*/
1941 0, /*tp_repr*/
1944 /* Stdwin methods */
1946 static object *
1947 stdwin_done(sw, args)
1948 object *sw;
1949 object *args;
1951 if (!getnoarg(args))
1952 return NULL;
1953 wdone();
1954 /* XXX There is no protection against continued use of
1955 XXX stdwin functions or objects after this call is made.
1956 XXX Use at own risk */
1957 INCREF(None);
1958 return None;
1961 static object *
1962 stdwin_open(sw, args)
1963 object *sw;
1964 object *args;
1966 int tag;
1967 object *title;
1968 windowobject *wp;
1969 if (!getargs(args, "S", &title))
1970 return NULL;
1971 for (tag = 0; tag < MAXNWIN; tag++) {
1972 if (windowlist[tag] == NULL)
1973 break;
1975 if (tag >= MAXNWIN) {
1976 err_setstr(StdwinError, "creating too many windows");
1977 return NULL;
1979 wp = NEWOBJ(windowobject, &Windowtype);
1980 if (wp == NULL)
1981 return NULL;
1982 INCREF(title);
1983 wp->w_title = title;
1984 wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL);
1985 wp->w_attr = NULL;
1986 if (wp->w_win == NULL) {
1987 DECREF(wp);
1988 return NULL;
1990 windowlist[tag] = wp;
1991 wsettag(wp->w_win, tag);
1992 return (object *)wp;
1995 static object *
1996 window2object(win)
1997 WINDOW *win;
1999 object *w;
2000 if (win == NULL)
2001 w = None;
2002 else {
2003 int tag = wgettag(win);
2004 if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL ||
2005 windowlist[tag]->w_win != win)
2006 w = None;
2007 else
2008 w = (object *)windowlist[tag];
2010 INCREF(w);
2011 return w;
2014 static object *
2015 stdwin_get_poll_event(poll, args)
2016 int poll;
2017 object *args;
2019 EVENT e;
2020 object *u, *v, *w;
2021 if (!getnoarg(args))
2022 return NULL;
2023 if (Drawing != NULL) {
2024 err_setstr(StdwinError, "cannot getevent() while drawing");
2025 return NULL;
2027 again:
2028 BGN_STDWIN
2029 if (poll) {
2030 if (!wpollevent(&e)) {
2031 RET_STDWIN
2032 INCREF(None);
2033 return None;
2036 else
2037 wgetevent(&e);
2038 END_STDWIN
2039 if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
2040 /* Turn keyboard interrupts into exceptions */
2041 err_set(KeyboardInterrupt);
2042 return NULL;
2044 if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) {
2045 /* Turn WC_CLOSE commands into WE_CLOSE events */
2046 e.type = WE_CLOSE;
2048 v = window2object(e.window);
2049 switch (e.type) {
2050 case WE_CHAR:
2052 char c[1];
2053 c[0] = e.u.character;
2054 w = newsizedstringobject(c, 1);
2056 break;
2057 case WE_COMMAND:
2058 w = newintobject((long)e.u.command);
2059 break;
2060 case WE_DRAW:
2061 w = makerect(e.u.area.left, e.u.area.top,
2062 e.u.area.right, e.u.area.bottom);
2063 break;
2064 case WE_MOUSE_DOWN:
2065 case WE_MOUSE_MOVE:
2066 case WE_MOUSE_UP:
2067 w = mkvalue("((ii)iii)",
2068 e.u.where.h, e.u.where.v,
2069 e.u.where.clicks,
2070 e.u.where.button,
2071 e.u.where.mask);
2072 break;
2073 case WE_MENU:
2074 if (e.u.m.id >= IDOFFSET && e.u.m.id < IDOFFSET+MAXNMENU &&
2075 menulist[e.u.m.id - IDOFFSET] != NULL)
2076 w = mkvalue("(Oi)",
2077 menulist[e.u.m.id - IDOFFSET], e.u.m.item);
2078 else {
2079 /* Ghost menu event.
2080 Can occur only on the Mac if another part
2081 of the aplication has installed a menu;
2082 like the THINK C console library. */
2083 DECREF(v);
2084 goto again;
2086 break;
2087 case WE_KEY:
2088 w = mkvalue("(ii)", e.u.key.code, e.u.key.mask);
2089 break;
2090 case WE_LOST_SEL:
2091 w = newintobject((long)e.u.sel);
2092 break;
2093 default:
2094 w = None;
2095 INCREF(w);
2096 break;
2098 if (w == NULL) {
2099 DECREF(v);
2100 return NULL;
2102 u = mkvalue("(iOO)", e.type, v, w);
2103 XDECREF(v);
2104 XDECREF(w);
2105 return u;
2108 static object *
2109 stdwin_getevent(sw, args)
2110 object *sw;
2111 object *args;
2113 return stdwin_get_poll_event(0, args);
2116 static object *
2117 stdwin_pollevent(sw, args)
2118 object *sw;
2119 object *args;
2121 return stdwin_get_poll_event(1, args);
2124 static object *
2125 stdwin_setdefwinpos(sw, args)
2126 object *sw;
2127 object *args;
2129 int a[2];
2130 if (!getpointarg(args, a))
2131 return NULL;
2132 wsetdefwinpos(a[0], a[1]);
2133 INCREF(None);
2134 return None;
2137 static object *
2138 stdwin_setdefwinsize(sw, args)
2139 object *sw;
2140 object *args;
2142 int a[2];
2143 if (!getpointarg(args, a))
2144 return NULL;
2145 wsetdefwinsize(a[0], a[1]);
2146 INCREF(None);
2147 return None;
2150 static object *
2151 stdwin_setdefscrollbars(sw, args)
2152 object *sw;
2153 object *args;
2155 int a[2];
2156 if (!getpointarg(args, a))
2157 return NULL;
2158 wsetdefscrollbars(a[0], a[1]);
2159 INCREF(None);
2160 return None;
2163 static object *
2164 stdwin_getdefwinpos(self, args)
2165 object *self;
2166 object *args;
2168 int h, v;
2169 if (!getnoarg(args))
2170 return NULL;
2171 wgetdefwinpos(&h, &v);
2172 return makepoint(h, v);
2175 static object *
2176 stdwin_getdefwinsize(self, args)
2177 object *self;
2178 object *args;
2180 int width, height;
2181 if (!getnoarg(args))
2182 return NULL;
2183 wgetdefwinsize(&width, &height);
2184 return makepoint(width, height);
2187 static object *
2188 stdwin_getdefscrollbars(self, args)
2189 object *self;
2190 object *args;
2192 int h, v;
2193 if (!getnoarg(args))
2194 return NULL;
2195 wgetdefscrollbars(&h, &v);
2196 return makepoint(h, v);
2199 static object *
2200 stdwin_menucreate(self, args)
2201 object *self;
2202 object *args;
2204 char *title;
2205 if (!getstrarg(args, &title))
2206 return NULL;
2207 wmenusetdeflocal(0);
2208 return (object *)newmenuobject(title);
2211 static object *
2212 stdwin_askfile(self, args)
2213 object *self;
2214 object *args;
2216 char *prompt, *dflt;
2217 int new, ret;
2218 char buf[256];
2219 if (!getargs(args, "(ssi)", &prompt, &dflt, &new))
2220 return NULL;
2221 strncpy(buf, dflt, sizeof buf);
2222 buf[sizeof buf - 1] = '\0';
2223 BGN_STDWIN
2224 ret = waskfile(prompt, buf, sizeof buf, new);
2225 END_STDWIN
2226 if (!ret) {
2227 err_set(KeyboardInterrupt);
2228 return NULL;
2230 return newstringobject(buf);
2233 static object *
2234 stdwin_askync(self, args)
2235 object *self;
2236 object *args;
2238 char *prompt;
2239 int new, ret;
2240 if (!getargs(args, "(si)", &prompt, &new))
2241 return NULL;
2242 BGN_STDWIN
2243 ret = waskync(prompt, new);
2244 END_STDWIN
2245 if (ret < 0) {
2246 err_set(KeyboardInterrupt);
2247 return NULL;
2249 return newintobject((long)ret);
2252 static object *
2253 stdwin_askstr(self, args)
2254 object *self;
2255 object *args;
2257 char *prompt, *dflt;
2258 int ret;
2259 char buf[256];
2260 if (!getargs(args, "(ss)", &prompt, &dflt))
2261 return NULL;
2262 strncpy(buf, dflt, sizeof buf);
2263 buf[sizeof buf - 1] = '\0';
2264 BGN_STDWIN
2265 ret = waskstr(prompt, buf, sizeof buf);
2266 END_STDWIN
2267 if (!ret) {
2268 err_set(KeyboardInterrupt);
2269 return NULL;
2271 return newstringobject(buf);
2274 static object *
2275 stdwin_message(self, args)
2276 object *self;
2277 object *args;
2279 char *msg;
2280 if (!getstrarg(args, &msg))
2281 return NULL;
2282 BGN_STDWIN
2283 wmessage(msg);
2284 END_STDWIN
2285 INCREF(None);
2286 return None;
2289 static object *
2290 stdwin_fleep(self, args)
2291 object *self;
2292 object *args;
2294 if (!getnoarg(args))
2295 return NULL;
2296 wfleep();
2297 INCREF(None);
2298 return None;
2301 static object *
2302 stdwin_setcutbuffer(self, args)
2303 object *self;
2304 object *args;
2306 int i, size;
2307 char *str;
2308 if (!getargs(args, "(is#)", &i, &str, &size))
2309 return NULL;
2310 wsetcutbuffer(i, str, size);
2311 INCREF(None);
2312 return None;
2315 static object *
2316 stdwin_getactive(self, args)
2317 object *self;
2318 object *args;
2320 return window2object(wgetactive());
2323 static object *
2324 stdwin_getcutbuffer(self, args)
2325 object *self;
2326 object *args;
2328 int i;
2329 char *str;
2330 int len;
2331 if (!getintarg(args, &i))
2332 return NULL;
2333 str = wgetcutbuffer(i, &len);
2334 if (str == NULL) {
2335 str = "";
2336 len = 0;
2338 return newsizedstringobject(str, len);
2341 static object *
2342 stdwin_rotatecutbuffers(self, args)
2343 object *self;
2344 object *args;
2346 int i;
2347 if (!getintarg(args, &i))
2348 return NULL;
2349 wrotatecutbuffers(i);
2350 INCREF(None);
2351 return None;
2354 static object *
2355 stdwin_getselection(self, args)
2356 object *self;
2357 object *args;
2359 int sel;
2360 char *data;
2361 int len;
2362 if (!getintarg(args, &sel))
2363 return NULL;
2364 data = wgetselection(sel, &len);
2365 if (data == NULL) {
2366 data = "";
2367 len = 0;
2369 return newsizedstringobject(data, len);
2372 static object *
2373 stdwin_resetselection(self, args)
2374 object *self;
2375 object *args;
2377 int sel;
2378 if (!getintarg(args, &sel))
2379 return NULL;
2380 wresetselection(sel);
2381 INCREF(None);
2382 return None;
2385 static object *
2386 stdwin_fetchcolor(self, args)
2387 object *self;
2388 object *args;
2390 char *colorname;
2391 COLOR color;
2392 if (!getstrarg(args, &colorname))
2393 return NULL;
2394 color = wfetchcolor(colorname);
2395 #ifdef BADCOLOR
2396 if (color == BADCOLOR) {
2397 err_setstr(StdwinError, "color name not found");
2398 return NULL;
2400 #endif
2401 return newintobject((long)color);
2404 static object *
2405 stdwin_getscrsize(self, args)
2406 object *self;
2407 object *args;
2409 int width, height;
2410 if (!getnoarg(args))
2411 return NULL;
2412 wgetscrsize(&width, &height);
2413 return makepoint(width, height);
2416 static object *
2417 stdwin_getscrmm(self, args)
2418 object *self;
2419 object *args;
2421 int width, height;
2422 if (!getnoarg(args))
2423 return NULL;
2424 wgetscrmm(&width, &height);
2425 return makepoint(width, height);
2428 #ifdef unix
2429 static object *
2430 stdwin_connectionnumber(self, args)
2431 object *self;
2432 object *args;
2434 if (!getnoarg(args))
2435 return NULL;
2436 return newintobject((long) wconnectionnumber());
2438 #endif
2440 static object *
2441 stdwin_listfontnames(self, args)
2442 object *self;
2443 object *args;
2445 char *pattern;
2446 char **fontnames;
2447 int count;
2448 object *list;
2449 if (!getargs(args, "z", &pattern))
2450 return NULL;
2451 fontnames = wlistfontnames(pattern, &count);
2452 list = newlistobject(count);
2453 if (list != NULL) {
2454 int i;
2455 for (i = 0; i < count; i++) {
2456 object *v = newstringobject(fontnames[i]);
2457 if (v == NULL) {
2458 DECREF(list);
2459 list = NULL;
2460 break;
2462 setlistitem(list, i, v);
2465 return list;
2468 #ifdef HAVE_BITMAPS
2469 static object *
2470 stdwin_newbitmap(self, args)
2471 object *self;
2472 object *args;
2474 int width, height;
2475 bitmapobject *bp;
2476 if (!getargs(args, "(ii)", &width, &height))
2477 return NULL;
2478 return (object *)newbitmapobject(width, height);
2480 #endif
2482 static struct methodlist stdwin_methods[] = {
2483 {"askfile", stdwin_askfile},
2484 {"askstr", stdwin_askstr},
2485 {"askync", stdwin_askync},
2486 {"done", stdwin_done},
2487 {"fetchcolor", stdwin_fetchcolor},
2488 #ifdef unix
2489 {"fileno", stdwin_connectionnumber},
2490 {"connectionnumber", stdwin_connectionnumber},
2491 #endif
2492 {"fleep", stdwin_fleep},
2493 {"getactive", stdwin_getactive},
2494 {"getcutbuffer", stdwin_getcutbuffer},
2495 {"getdefscrollbars", stdwin_getdefscrollbars},
2496 {"getdefwinpos", stdwin_getdefwinpos},
2497 {"getdefwinsize", stdwin_getdefwinsize},
2498 {"getevent", stdwin_getevent},
2499 {"getscrmm", stdwin_getscrmm},
2500 {"getscrsize", stdwin_getscrsize},
2501 {"getselection", stdwin_getselection},
2502 {"listfontnames", stdwin_listfontnames},
2503 {"menucreate", stdwin_menucreate},
2504 {"message", stdwin_message},
2505 #ifdef HAVE_BITMAPS
2506 {"newbitmap", stdwin_newbitmap},
2507 #endif
2508 {"open", stdwin_open},
2509 {"pollevent", stdwin_pollevent},
2510 {"resetselection", stdwin_resetselection},
2511 {"rotatecutbuffers", stdwin_rotatecutbuffers},
2512 {"setcutbuffer", stdwin_setcutbuffer},
2513 {"setdefscrollbars", stdwin_setdefscrollbars},
2514 {"setdefwinpos", stdwin_setdefwinpos},
2515 {"setdefwinsize", stdwin_setdefwinsize},
2517 /* Text measuring methods borrow code from drawing objects: */
2518 {"baseline", drawing_baseline},
2519 {"lineheight", drawing_lineheight},
2520 {"textbreak", drawing_textbreak},
2521 {"textwidth", drawing_textwidth},
2523 /* Same for font setting methods: */
2524 {"setfont", drawing_setfont},
2526 /* Same for color setting/getting methods: */
2527 {"getbgcolor", drawing_getbgcolor},
2528 {"getfgcolor", drawing_getfgcolor},
2529 {"setbgcolor", drawing_setbgcolor},
2530 {"setfgcolor", drawing_setfgcolor},
2532 {NULL, NULL} /* sentinel */
2535 static int
2536 checkstringlist(args, ps, pn)
2537 object *args;
2538 char ***ps;
2539 int *pn;
2541 int i, n;
2542 char **s;
2543 if (!is_listobject(args)) {
2544 err_setstr(TypeError, "list of strings expected");
2545 return 0;
2547 n = getlistsize(args);
2548 s = NEW(char *, n+1);
2549 if (s == NULL) {
2550 err_nomem();
2551 return 0;
2553 for (i = 0; i < n; i++) {
2554 object *item = getlistitem(args, i);
2555 if (!is_stringobject(item)) {
2556 err_setstr(TypeError, "list of strings expected");
2557 return 0;
2559 s[i] = getstringvalue(item);
2561 s[n] = NULL; /* In case caller wants a NULL-terminated list */
2562 *ps = s;
2563 *pn = n;
2564 return 1;
2567 static int
2568 putbackstringlist(list, s, n)
2569 object *list;
2570 char **s;
2571 int n;
2573 int oldsize = getlistsize(list);
2574 object *newlist;
2575 int i;
2576 if (n == oldsize)
2577 return 1;
2578 newlist = newlistobject(n);
2579 for (i = 0; i < n && newlist != NULL; i++) {
2580 object *item = newstringobject(s[i]);
2581 if (item == NULL) {
2582 DECREF(newlist);
2583 newlist = NULL;
2585 else
2586 setlistitem(newlist, i, item);
2588 if (newlist == NULL)
2589 return 0;
2590 (*list->ob_type->tp_as_sequence->sq_ass_slice)
2591 (list, 0, oldsize, newlist);
2592 DECREF(newlist);
2593 return 1;
2596 void
2597 initstdwin()
2599 object *m, *d;
2600 static int inited = 0;
2601 char buf[1000];
2603 if (!inited) {
2604 int argc = 0;
2605 char **argv = NULL;
2606 object *sys_argv = sysget("argv");
2607 if (sys_argv != NULL) {
2608 if (!checkstringlist(sys_argv, &argv, &argc))
2609 err_clear();
2611 if (argc > 0) {
2612 /* If argv[0] has a ".py" suffix, remove the suffix */
2613 char *p = strrchr(argv[0], '.');
2614 if (p != NULL && strcmp(p, ".py") == 0) {
2615 int n = p - argv[0];
2616 if (n >= sizeof(buf))
2617 n = sizeof(buf)-1;
2618 strncpy(buf, argv[0], n);
2619 buf[n] = '\0';
2620 argv[0] = buf;
2623 winitargs(&argc, &argv);
2624 if (argv != NULL) {
2625 if (!putbackstringlist(sys_argv, argv, argc))
2626 err_clear();
2628 inited = 1;
2630 m = initmodule("stdwin", stdwin_methods);
2631 d = getmoduledict(m);
2633 /* Initialize stdwin.error exception */
2634 StdwinError = newstringobject("stdwin.error");
2635 if (StdwinError == NULL || dictinsert(d, "error", StdwinError) != 0)
2636 fatal("can't define stdwin.error");
2637 #ifdef USE_THREAD
2638 StdwinLock = allocate_lock();
2639 if (StdwinLock == NULL)
2640 fatal("can't allocate stdwin lock");
2641 #endif