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