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