blob: 4d28f9735824ca40e53f4e687f323a90ea475c36 [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* Stdwin module */
2
3/* Stdwin itself is a module, not a separate object type.
4 Object types defined here:
5 wp: a window
6 dp: a drawing structure (only one can exist at a time)
7 mp: a menu
8 tp: a textedit block
9*/
10
11/* Rules for translating C stdwin function calls into Python stwin:
12 - All names drop their initial letter 'w'
13 - Functions with a window as first parameter are methods of window objects
14 - There is no equivalent for wclose(); just delete the window object
15 (all references to it!) (XXX maybe this is a bad idea)
16 - w.begindrawing() returns a drawing object
17 - There is no equivalent for wenddrawing(win); just delete the drawing
18 object (all references to it!) (XXX maybe this is a bad idea)
19 - Functions that may only be used inside wbegindrawing / wendddrawing
20 are methods of the drawing object; this includes the text measurement
21 functions (which however have doubles as module functions).
22 - Methods of the drawing object drop an initial 'draw' from their name
23 if they have it, e.g., wdrawline() --> d.line()
24 - The obvious type conversions: int --> intobject; string --> stringobject
25 - A text parameter followed by a length parameter is only a text (string)
26 parameter in Python
27 - A point or other pair of horizontal and vertical coordinates is always
28 a pair of integers in Python
29 - Two points forming a rectangle or endpoints of a line segment are a
30 pair of points in Python
31 - The arguments to d.elarc() are three points.
32 - The functions wgetclip() and wsetclip() are translated into
33 stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
34 a bad word for what these functions do (clipping has a different
35 meaning in the drawing world), while cutbuffer is standard X jargon.
Guido van Rossum01769f01990-10-30 13:39:00 +000036 XXX This must change again in the light of changes to stdwin!
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000037 - For textedit, similar rules hold, but they are less strict.
38 XXX more?
39*/
40
Guido van Rossum3f5da241990-12-20 15:06:42 +000041#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000042
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044
Guido van Rossum3f5da241990-12-20 15:06:42 +000045#include "stdwin.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000046
47/* Window and menu object types declared here because of forward references */
48
49typedef struct {
50 OB_HEAD
51 object *w_title;
52 WINDOW *w_win;
53 object *w_attr; /* Attributes dictionary */
54} windowobject;
55
56extern typeobject Windowtype; /* Really static, forward */
57
58#define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
59
60typedef struct {
61 OB_HEAD
62 MENU *m_menu;
63 int m_id;
64 object *m_attr; /* Attributes dictionary */
65} menuobject;
66
67extern typeobject Menutype; /* Really static, forward */
68
69#define is_menuobject(mp) ((mp)->ob_type == &Menutype)
70
71
72/* Strongly stdwin-specific argument handlers */
73
74static int
75getmousedetail(v, ep)
76 object *v;
77 EVENT *ep;
78{
79 if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 4)
80 return err_badarg();
81 return getintintarg(gettupleitem(v, 0),
82 &ep->u.where.h, &ep->u.where.v) &&
83 getintarg(gettupleitem(v, 1), &ep->u.where.clicks) &&
84 getintarg(gettupleitem(v, 2), &ep->u.where.button) &&
85 getintarg(gettupleitem(v, 3), &ep->u.where.mask);
86}
87
88static int
89getmenudetail(v, ep)
90 object *v;
91 EVENT *ep;
92{
93 object *mp;
94 if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
95 return err_badarg();
96 mp = gettupleitem(v, 0);
97 if (mp == NULL || !is_menuobject(mp))
98 return err_badarg();
99 ep->u.m.id = ((menuobject *)mp) -> m_id;
100 return getintarg(gettupleitem(v, 1), &ep->u.m.item);
101}
102
103static int
104geteventarg(v, ep)
105 object *v;
106 EVENT *ep;
107{
108 object *wp, *detail;
109 int a[4];
110 if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3)
111 return err_badarg();
112 if (!getintarg(gettupleitem(v, 0), &ep->type))
113 return 0;
114 wp = gettupleitem(v, 1);
115 if (wp == None)
116 ep->window = NULL;
117 else if (wp == NULL || !is_windowobject(wp))
118 return err_badarg();
119 else
120 ep->window = ((windowobject *)wp) -> w_win;
121 detail = gettupleitem(v, 2);
122 switch (ep->type) {
123 case WE_CHAR:
124 if (!is_stringobject(detail) || getstringsize(detail) != 1)
125 return err_badarg();
126 ep->u.character = getstringvalue(detail)[0];
127 return 1;
128 case WE_COMMAND:
129 return getintarg(detail, &ep->u.command);
130 case WE_DRAW:
131 if (!getrectarg(detail, a))
132 return 0;
133 ep->u.area.left = a[0];
134 ep->u.area.top = a[1];
135 ep->u.area.right = a[2];
136 ep->u.area.bottom = a[3];
137 return 1;
138 case WE_MOUSE_DOWN:
139 case WE_MOUSE_UP:
140 case WE_MOUSE_MOVE:
141 return getmousedetail(detail, ep);
142 case WE_MENU:
143 return getmenudetail(detail, ep);
144 default:
145 return 1;
146 }
147}
148
149
150/* Return construction tools */
151
152static object *
153makepoint(a, b)
154 int a, b;
155{
156 object *v;
157 object *w;
158 if ((v = newtupleobject(2)) == NULL)
159 return NULL;
160 if ((w = newintobject((long)a)) == NULL ||
161 settupleitem(v, 0, w) != 0 ||
162 (w = newintobject((long)b)) == NULL ||
163 settupleitem(v, 1, w) != 0) {
164 DECREF(v);
165 return NULL;
166 }
167 return v;
168}
169
170static object *
171makerect(a, b, c, d)
172 int a, b, c, d;
173{
174 object *v;
175 object *w;
176 if ((v = newtupleobject(2)) == NULL)
177 return NULL;
178 if ((w = makepoint(a, b)) == NULL ||
179 settupleitem(v, 0, w) != 0 ||
180 (w = makepoint(c, d)) == NULL ||
181 settupleitem(v, 1, w) != 0) {
182 DECREF(v);
183 return NULL;
184 }
185 return v;
186}
187
188static object *
189makemouse(hor, ver, clicks, button, mask)
190 int hor, ver, clicks, button, mask;
191{
192 object *v;
193 object *w;
194 if ((v = newtupleobject(4)) == NULL)
195 return NULL;
196 if ((w = makepoint(hor, ver)) == NULL ||
197 settupleitem(v, 0, w) != 0 ||
198 (w = newintobject((long)clicks)) == NULL ||
199 settupleitem(v, 1, w) != 0 ||
200 (w = newintobject((long)button)) == NULL ||
201 settupleitem(v, 2, w) != 0 ||
202 (w = newintobject((long)mask)) == NULL ||
203 settupleitem(v, 3, w) != 0) {
204 DECREF(v);
205 return NULL;
206 }
207 return v;
208}
209
210static object *
211makemenu(mp, item)
212 object *mp;
213 int item;
214{
215 object *v;
216 object *w;
217 if ((v = newtupleobject(2)) == NULL)
218 return NULL;
219 INCREF(mp);
220 if (settupleitem(v, 0, mp) != 0 ||
221 (w = newintobject((long)item)) == NULL ||
222 settupleitem(v, 1, w) != 0) {
223 DECREF(v);
224 return NULL;
225 }
226 return v;
227}
228
229
230/* Drawing objects */
231
232typedef struct {
233 OB_HEAD
234 windowobject *d_ref;
235} drawingobject;
236
237static drawingobject *Drawing; /* Set to current drawing object, or NULL */
238
239/* Drawing methods */
240
241static void
242drawing_dealloc(dp)
243 drawingobject *dp;
244{
245 wenddrawing(dp->d_ref->w_win);
246 Drawing = NULL;
247 DECREF(dp->d_ref);
248 free((char *)dp);
249}
250
251static object *
252drawing_generic(dp, args, func)
253 drawingobject *dp;
254 object *args;
255 void (*func) FPROTO((int, int, int, int));
256{
257 int a[4];
258 if (!getrectarg(args, a))
259 return NULL;
260 (*func)(a[0], a[1], a[2], a[3]);
261 INCREF(None);
262 return None;
263}
264
265static object *
266drawing_line(dp, args)
267 drawingobject *dp;
268 object *args;
269{
270 drawing_generic(dp, args, wdrawline);
271}
272
273static object *
274drawing_xorline(dp, args)
275 drawingobject *dp;
276 object *args;
277{
278 drawing_generic(dp, args, wxorline);
279}
280
281static object *
282drawing_circle(dp, args)
283 drawingobject *dp;
284 object *args;
285{
286 int a[3];
287 if (!getpointintarg(args, a))
288 return NULL;
289 wdrawcircle(a[0], a[1], a[2]);
290 INCREF(None);
291 return None;
292}
293
294static object *
295drawing_elarc(dp, args)
296 drawingobject *dp;
297 object *args;
298{
299 int a[6];
300 if (!get3pointarg(args, a))
301 return NULL;
302 wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
303 INCREF(None);
304 return None;
305}
306
307static object *
308drawing_box(dp, args)
309 drawingobject *dp;
310 object *args;
311{
312 drawing_generic(dp, args, wdrawbox);
313}
314
315static object *
316drawing_erase(dp, args)
317 drawingobject *dp;
318 object *args;
319{
320 drawing_generic(dp, args, werase);
321}
322
323static object *
324drawing_paint(dp, args)
325 drawingobject *dp;
326 object *args;
327{
328 drawing_generic(dp, args, wpaint);
329}
330
331static object *
332drawing_invert(dp, args)
333 drawingobject *dp;
334 object *args;
335{
336 drawing_generic(dp, args, winvert);
337}
338
339static object *
340drawing_cliprect(dp, args)
341 drawingobject *dp;
342 object *args;
343{
344 drawing_generic(dp, args, wcliprect);
345}
346
347static object *
348drawing_noclip(dp, args)
349 drawingobject *dp;
350 object *args;
351{
352 if (!getnoarg(args))
353 return NULL;
354 wnoclip();
355 INCREF(None);
356 return None;
357}
358
359static object *
360drawing_shade(dp, args)
361 drawingobject *dp;
362 object *args;
363{
364 int a[5];
365 if (!getrectintarg(args, a))
366 return NULL;
367 wshade(a[0], a[1], a[2], a[3], a[4]);
368 INCREF(None);
369 return None;
370}
371
372static object *
373drawing_text(dp, args)
374 drawingobject *dp;
375 object *args;
376{
377 int a[2];
378 object *s;
379 if (!getpointstrarg(args, a, &s))
380 return NULL;
381 wdrawtext(a[0], a[1], getstringvalue(s), (int)getstringsize(s));
382 INCREF(None);
383 return None;
384}
385
386/* The following four are also used as stdwin functions */
387
388static object *
389drawing_lineheight(dp, args)
390 drawingobject *dp;
391 object *args;
392{
393 if (!getnoarg(args))
394 return NULL;
395 return newintobject((long)wlineheight());
396}
397
398static object *
399drawing_baseline(dp, args)
400 drawingobject *dp;
401 object *args;
402{
403 if (!getnoarg(args))
404 return NULL;
405 return newintobject((long)wbaseline());
406}
407
408static object *
409drawing_textwidth(dp, args)
410 drawingobject *dp;
411 object *args;
412{
413 object *s;
414 if (!getstrarg(args, &s))
415 return NULL;
416 return newintobject(
417 (long)wtextwidth(getstringvalue(s), (int)getstringsize(s)));
418}
419
420static object *
421drawing_textbreak(dp, args)
422 drawingobject *dp;
423 object *args;
424{
425 object *s;
426 int a;
427 if (!getstrintarg(args, &s, &a))
428 return NULL;
429 return newintobject(
430 (long)wtextbreak(getstringvalue(s), (int)getstringsize(s), a));
431}
432
433static struct methodlist drawing_methods[] = {
434 {"box", drawing_box},
435 {"circle", drawing_circle},
436 {"cliprect", drawing_cliprect},
437 {"elarc", drawing_elarc},
438 {"erase", drawing_erase},
439 {"invert", drawing_invert},
440 {"line", drawing_line},
441 {"noclip", drawing_noclip},
442 {"paint", drawing_paint},
443 {"shade", drawing_shade},
444 {"text", drawing_text},
445 {"xorline", drawing_xorline},
446
447 /* Text measuring methods: */
448 {"baseline", drawing_baseline},
449 {"lineheight", drawing_lineheight},
450 {"textbreak", drawing_textbreak},
451 {"textwidth", drawing_textwidth},
452 {NULL, NULL} /* sentinel */
453};
454
455static object *
456drawing_getattr(wp, name)
457 drawingobject *wp;
458 char *name;
459{
460 return findmethod(drawing_methods, (object *)wp, name);
461}
462
463static typeobject Drawingtype = {
464 OB_HEAD_INIT(&Typetype)
465 0, /*ob_size*/
466 "drawing", /*tp_name*/
467 sizeof(drawingobject), /*tp_size*/
468 0, /*tp_itemsize*/
469 /* methods */
470 drawing_dealloc, /*tp_dealloc*/
471 0, /*tp_print*/
472 drawing_getattr, /*tp_getattr*/
473 0, /*tp_setattr*/
474 0, /*tp_compare*/
475 0, /*tp_repr*/
476};
477
478
479/* Text(edit) objects */
480
481typedef struct {
482 OB_HEAD
483 TEXTEDIT *t_text;
484 windowobject *t_ref;
485 object *t_attr; /* Attributes dictionary */
486} textobject;
487
488extern typeobject Texttype; /* Really static, forward */
489
490static textobject *
491newtextobject(wp, left, top, right, bottom)
492 windowobject *wp;
493 int left, top, right, bottom;
494{
495 textobject *tp;
496 tp = NEWOBJ(textobject, &Texttype);
497 if (tp == NULL)
498 return NULL;
499 tp->t_attr = NULL;
500 INCREF(wp);
501 tp->t_ref = wp;
502 tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
503 if (tp->t_text == NULL) {
504 DECREF(tp);
505 return (textobject *) err_nomem();
506 }
507 return tp;
508}
509
510/* Text(edit) methods */
511
512static void
513text_dealloc(tp)
514 textobject *tp;
515{
516 if (tp->t_text != NULL)
517 tefree(tp->t_text);
518 if (tp->t_attr != NULL)
519 DECREF(tp->t_attr);
520 DECREF(tp->t_ref);
521 DEL(tp);
522}
523
524static object *
525text_arrow(self, args)
526 textobject *self;
527 object *args;
528{
529 int code;
530 if (!getintarg(args, &code))
531 return NULL;
532 tearrow(self->t_text, code);
533 INCREF(None);
534 return None;
535}
536
537static object *
538text_draw(self, args)
539 textobject *self;
540 object *args;
541{
542 register TEXTEDIT *tp = self->t_text;
543 int a[4];
544 int left, top, right, bottom;
545 if (!getrectarg(args, a))
546 return NULL;
547 if (Drawing != NULL) {
548 err_setstr(RuntimeError, "not drawing");
549 return NULL;
550 }
551 /* Clip to text area and ignore if area is empty */
552 left = tegetleft(tp);
553 top = tegettop(tp);
554 right = tegetright(tp);
555 bottom = tegetbottom(tp);
556 if (a[0] < left) a[0] = left;
557 if (a[1] < top) a[1] = top;
558 if (a[2] > right) a[2] = right;
559 if (a[3] > bottom) a[3] = bottom;
560 if (a[0] < a[2] && a[1] < a[3]) {
561 /* Hide/show focus around draw call; these are undocumented,
562 but required here to get the highlighting correct.
563 The call to werase is also required for this reason.
564 Finally, this forces us to require (above) that we are NOT
565 already drawing. */
566 tehidefocus(tp);
567 wbegindrawing(self->t_ref->w_win);
568 werase(a[0], a[1], a[2], a[3]);
569 tedrawnew(tp, a[0], a[1], a[2], a[3]);
570 wenddrawing(self->t_ref->w_win);
571 teshowfocus(tp);
572 }
573 INCREF(None);
574 return None;
575}
576
577static object *
578text_event(self, args)
579 textobject *self;
580 object *args;
581{
582 register TEXTEDIT *tp = self->t_text;
583 EVENT e;
584 if (!geteventarg(args, &e))
585 return NULL;
586 if (e.type == WE_MOUSE_DOWN) {
Guido van Rossum33f17701991-02-13 23:19:39 +0000587 /* Cheat at the margins */
588 int width, height;
589 wgetdocsize(e.window, &width, &height);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000590 if (e.u.where.h < 0 && tegetleft(tp) == 0)
591 e.u.where.h = 0;
Guido van Rossum33f17701991-02-13 23:19:39 +0000592 else if (e.u.where.h > width && tegetright(tp) == width)
593 e.u.where.h = width;
594 if (e.u.where.v < 0 && tegettop(tp) == 0)
595 e.u.where.v = 0;
596 else if (e.u.where.v > height && tegetright(tp) == height)
597 e.u.where.v = height;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000598 }
599 return newintobject((long) teevent(tp, &e));
600}
601
602static object *
603text_getfocus(self, args)
604 textobject *self;
605 object *args;
606{
607 if (!getnoarg(args))
608 return NULL;
609 return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
610}
611
612static object *
613text_getfocustext(self, args)
614 textobject *self;
615 object *args;
616{
617 int f1, f2;
618 char *text;
619 if (!getnoarg(args))
620 return NULL;
621 f1 = tegetfoc1(self->t_text);
622 f2 = tegetfoc2(self->t_text);
623 text = tegettext(self->t_text);
624 return newsizedstringobject(text + f1, f2-f1);
625}
626
627static object *
628text_getrect(self, args)
629 textobject *self;
630 object *args;
631{
632 if (!getnoarg(args))
633 return NULL;
634 return makerect(tegetleft(self->t_text),
635 tegettop(self->t_text),
636 tegetright(self->t_text),
637 tegetbottom(self->t_text));
638}
639
640static object *
641text_gettext(self, args)
642 textobject *self;
643 object *args;
644{
645 if (!getnoarg(args))
646 return NULL;
647 return newsizedstringobject(tegettext(self->t_text),
648 tegetlen(self->t_text));
649}
650
651static object *
652text_move(self, args)
653 textobject *self;
654 object *args;
655{
656 int a[4];
657 if (!getrectarg(args, a))
658 return NULL;
659 temovenew(self->t_text, a[0], a[1], a[2], a[3]);
660 INCREF(None);
661 return None;
662}
663
664static object *
665text_setfocus(self, args)
666 textobject *self;
667 object *args;
668{
669 int a[2];
670 if (!getpointarg(args, a))
671 return NULL;
672 tesetfocus(self->t_text, a[0], a[1]);
673 INCREF(None);
674 return None;
675}
676
677static object *
678text_replace(self, args)
679 textobject *self;
680 object *args;
681{
682 object *text;
683 if (!getstrarg(args, &text))
684 return NULL;
685 tereplace(self->t_text, getstringvalue(text));
686 INCREF(None);
687 return None;
688}
689
690static struct methodlist text_methods[] = {
691 "arrow", text_arrow,
692 "draw", text_draw,
693 "event", text_event,
694 "getfocus", text_getfocus,
695 "getfocustext", text_getfocustext,
696 "getrect", text_getrect,
697 "gettext", text_gettext,
698 "move", text_move,
699 "replace", text_replace,
700 "setfocus", text_setfocus,
701 {NULL, NULL} /* sentinel */
702};
703
704static object *
705text_getattr(tp, name)
706 textobject *tp;
707 char *name;
708{
709 if (tp->t_attr != NULL) {
710 object *v = dictlookup(tp->t_attr, name);
711 if (v != NULL) {
712 INCREF(v);
713 return v;
714 }
715 }
716 return findmethod(text_methods, (object *)tp, name);
717}
718
719static int
720text_setattr(tp, name, v)
721 textobject *tp;
722 char *name;
723 object *v;
724{
725 if (tp->t_attr == NULL) {
726 tp->t_attr = newdictobject();
727 if (tp->t_attr == NULL)
728 return -1;
729 }
730 if (v == NULL)
731 return dictremove(tp->t_attr, name);
732 else
733 return dictinsert(tp->t_attr, name, v);
734}
735
736static typeobject Texttype = {
737 OB_HEAD_INIT(&Typetype)
738 0, /*ob_size*/
739 "textedit", /*tp_name*/
740 sizeof(textobject), /*tp_size*/
741 0, /*tp_itemsize*/
742 /* methods */
743 text_dealloc, /*tp_dealloc*/
744 0, /*tp_print*/
745 text_getattr, /*tp_getattr*/
746 text_setattr, /*tp_setattr*/
747 0, /*tp_compare*/
748 0, /*tp_repr*/
749};
750
751
752/* Menu objects */
753
754#define MAXNMENU 50
755static menuobject *menulist[MAXNMENU]; /* Slot 0 unused */
756
757static menuobject *
758newmenuobject(title)
759 object *title;
760{
761 int id;
762 MENU *menu;
763 menuobject *mp;
764 for (id = 1; id < MAXNMENU; id++) {
765 if (menulist[id] == NULL)
766 break;
767 }
768 if (id >= MAXNMENU)
769 return (menuobject *) err_nomem();
770 menu = wmenucreate(id, getstringvalue(title));
771 if (menu == NULL)
772 return (menuobject *) err_nomem();
773 mp = NEWOBJ(menuobject, &Menutype);
774 if (mp != NULL) {
775 mp->m_menu = menu;
776 mp->m_id = id;
777 mp->m_attr = NULL;
778 menulist[id] = mp;
779 }
780 else
781 wmenudelete(menu);
782 return mp;
783}
784
785/* Menu methods */
786
787static void
788menu_dealloc(mp)
789 menuobject *mp;
790{
791
792 int id = mp->m_id;
793 if (id >= 0 && id < MAXNMENU) {
794 menulist[id] = NULL;
795 }
796 wmenudelete(mp->m_menu);
797 if (mp->m_attr != NULL)
798 DECREF(mp->m_attr);
799 DEL(mp);
800}
801
802static object *
803menu_additem(self, args)
804 menuobject *self;
805 object *args;
806{
807 object *text;
808 int shortcut;
809 if (is_tupleobject(args)) {
810 object *v;
811 if (!getstrstrarg(args, &text, &v))
812 return NULL;
813 if (getstringsize(v) != 1) {
814 err_badarg();
815 return NULL;
816 }
817 shortcut = *getstringvalue(v) & 0xff;
818 }
819 else {
820 if (!getstrarg(args, &text))
821 return NULL;
822 shortcut = -1;
823 }
824 wmenuadditem(self->m_menu, getstringvalue(text), shortcut);
825 INCREF(None);
826 return None;
827}
828
829static object *
830menu_setitem(self, args)
831 menuobject *self;
832 object *args;
833{
834 int index;
835 object *text;
836 if (!getintstrarg(args, &index, &text))
837 return NULL;
838 wmenusetitem(self->m_menu, index, getstringvalue(text));
839 INCREF(None);
840 return None;
841}
842
843static object *
844menu_enable(self, args)
845 menuobject *self;
846 object *args;
847{
848 int index;
849 int flag;
850 if (!getintintarg(args, &index, &flag))
851 return NULL;
852 wmenuenable(self->m_menu, index, flag);
853 INCREF(None);
854 return None;
855}
856
857static object *
858menu_check(self, args)
859 menuobject *self;
860 object *args;
861{
862 int index;
863 int flag;
864 if (!getintintarg(args, &index, &flag))
865 return NULL;
866 wmenucheck(self->m_menu, index, flag);
867 INCREF(None);
868 return None;
869}
870
871static struct methodlist menu_methods[] = {
872 "additem", menu_additem,
873 "setitem", menu_setitem,
874 "enable", menu_enable,
875 "check", menu_check,
876 {NULL, NULL} /* sentinel */
877};
878
879static object *
880menu_getattr(mp, name)
881 menuobject *mp;
882 char *name;
883{
884 if (mp->m_attr != NULL) {
885 object *v = dictlookup(mp->m_attr, name);
886 if (v != NULL) {
887 INCREF(v);
888 return v;
889 }
890 }
891 return findmethod(menu_methods, (object *)mp, name);
892}
893
894static int
895menu_setattr(mp, name, v)
896 menuobject *mp;
897 char *name;
898 object *v;
899{
900 if (mp->m_attr == NULL) {
901 mp->m_attr = newdictobject();
902 if (mp->m_attr == NULL)
903 return -1;
904 }
905 if (v == NULL)
906 return dictremove(mp->m_attr, name);
907 else
908 return dictinsert(mp->m_attr, name, v);
909}
910
911static typeobject Menutype = {
912 OB_HEAD_INIT(&Typetype)
913 0, /*ob_size*/
914 "menu", /*tp_name*/
915 sizeof(menuobject), /*tp_size*/
916 0, /*tp_itemsize*/
917 /* methods */
918 menu_dealloc, /*tp_dealloc*/
919 0, /*tp_print*/
920 menu_getattr, /*tp_getattr*/
921 menu_setattr, /*tp_setattr*/
922 0, /*tp_compare*/
923 0, /*tp_repr*/
924};
925
926
927/* Windows */
928
929#define MAXNWIN 50
930static windowobject *windowlist[MAXNWIN];
931
932/* Window methods */
933
934static void
935window_dealloc(wp)
936 windowobject *wp;
937{
938 if (wp->w_win != NULL) {
939 int tag = wgettag(wp->w_win);
940 if (tag >= 0 && tag < MAXNWIN)
941 windowlist[tag] = NULL;
942 else
943 fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
944 tag);
945 wclose(wp->w_win);
946 }
947 DECREF(wp->w_title);
948 if (wp->w_attr != NULL)
949 DECREF(wp->w_attr);
950 free((char *)wp);
951}
952
953static void
954window_print(wp, fp, flags)
955 windowobject *wp;
956 FILE *fp;
957 int flags;
958{
959 fprintf(fp, "<window titled '%s'>", getstringvalue(wp->w_title));
960}
961
962static object *
963window_begindrawing(wp, args)
964 windowobject *wp;
965 object *args;
966{
967 drawingobject *dp;
968 if (!getnoarg(args))
969 return NULL;
970 if (Drawing != NULL) {
971 err_setstr(RuntimeError, "already drawing");
972 return NULL;
973 }
974 dp = NEWOBJ(drawingobject, &Drawingtype);
975 if (dp == NULL)
976 return NULL;
977 Drawing = dp;
978 INCREF(wp);
979 dp->d_ref = wp;
980 wbegindrawing(wp->w_win);
981 return (object *)dp;
982}
983
984static object *
985window_change(wp, args)
986 windowobject *wp;
987 object *args;
988{
989 int a[4];
990 if (!getrectarg(args, a))
991 return NULL;
992 wchange(wp->w_win, a[0], a[1], a[2], a[3]);
993 INCREF(None);
994 return None;
995}
996
997static object *
998window_gettitle(wp, args)
999 windowobject *wp;
1000 object *args;
1001{
1002 if (!getnoarg(args))
1003 return NULL;
1004 INCREF(wp->w_title);
1005 return wp->w_title;
1006}
1007
1008static object *
1009window_getwinsize(wp, args)
1010 windowobject *wp;
1011 object *args;
1012{
1013 int width, height;
1014 if (!getnoarg(args))
1015 return NULL;
1016 wgetwinsize(wp->w_win, &width, &height);
1017 return makepoint(width, height);
1018}
1019
1020static object *
1021window_getdocsize(wp, args)
1022 windowobject *wp;
1023 object *args;
1024{
1025 int width, height;
1026 if (!getnoarg(args))
1027 return NULL;
1028 wgetdocsize(wp->w_win, &width, &height);
1029 return makepoint(width, height);
1030}
1031
1032static object *
1033window_getorigin(wp, args)
1034 windowobject *wp;
1035 object *args;
1036{
1037 int width, height;
1038 if (!getnoarg(args))
1039 return NULL;
1040 wgetorigin(wp->w_win, &width, &height);
1041 return makepoint(width, height);
1042}
1043
1044static object *
1045window_scroll(wp, args)
1046 windowobject *wp;
1047 object *args;
1048{
1049 int a[6];
1050 if (!getrectpointarg(args, a))
1051 return NULL;
1052 wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
1053 INCREF(None);
1054 return None;
1055}
1056
1057static object *
1058window_setdocsize(wp, args)
1059 windowobject *wp;
1060 object *args;
1061{
1062 int a[2];
1063 if (!getpointarg(args, a))
1064 return NULL;
1065 wsetdocsize(wp->w_win, a[0], a[1]);
1066 INCREF(None);
1067 return None;
1068}
1069
1070static object *
1071window_setorigin(wp, args)
1072 windowobject *wp;
1073 object *args;
1074{
1075 int a[2];
1076 if (!getpointarg(args, a))
1077 return NULL;
1078 wsetorigin(wp->w_win, a[0], a[1]);
1079 INCREF(None);
1080 return None;
1081}
1082
1083static object *
1084window_settitle(wp, args)
1085 windowobject *wp;
1086 object *args;
1087{
1088 object *title;
1089 if (!getstrarg(args, &title))
1090 return NULL;
1091 DECREF(wp->w_title);
1092 INCREF(title);
1093 wp->w_title = title;
1094 wsettitle(wp->w_win, getstringvalue(title));
1095 INCREF(None);
1096 return None;
1097}
1098
1099static object *
1100window_show(wp, args)
1101 windowobject *wp;
1102 object *args;
1103{
1104 int a[4];
1105 if (!getrectarg(args, a))
1106 return NULL;
1107 wshow(wp->w_win, a[0], a[1], a[2], a[3]);
1108 INCREF(None);
1109 return None;
1110}
1111
1112static object *
1113window_settimer(wp, args)
1114 windowobject *wp;
1115 object *args;
1116{
1117 int a;
1118 if (!getintarg(args, &a))
1119 return NULL;
1120 wsettimer(wp->w_win, a);
1121 INCREF(None);
1122 return None;
1123}
1124
1125static object *
1126window_menucreate(self, args)
1127 windowobject *self;
1128 object *args;
1129{
1130 menuobject *mp;
1131 object *title;
1132 if (!getstrarg(args, &title))
1133 return NULL;
1134 wmenusetdeflocal(1);
1135 mp = newmenuobject(title);
1136 if (mp == NULL)
1137 return NULL;
1138 wmenuattach(self->w_win, mp->m_menu);
1139 return (object *)mp;
1140}
1141
1142static object *
1143window_textcreate(self, args)
1144 windowobject *self;
1145 object *args;
1146{
1147 textobject *tp;
1148 int a[4];
1149 if (!getrectarg(args, a))
1150 return NULL;
1151 return (object *)
1152 newtextobject(self, a[0], a[1], a[2], a[3]);
1153}
1154
Guido van Rossum5b10f451990-10-30 16:01:48 +00001155static object *
1156window_setselection(self, args)
1157 windowobject *self;
1158 object *args;
1159{
1160 int sel;
1161 object *str;
1162 int ok;
1163 if (!getintstrarg(args, &sel, &str))
1164 return NULL;
1165 ok = wsetselection(self->w_win, sel,
1166 getstringvalue(str), (int)getstringsize(str));
1167 return newintobject(ok);
1168}
1169
1170static object *
1171window_setwincursor(self, args)
1172 windowobject *self;
1173 object *args;
1174{
1175 object *str;
1176 CURSOR *c;
1177 if (!getstrarg(args, &str))
1178 return NULL;
1179 c = wfetchcursor(getstringvalue(str));
1180 if (c == NULL) {
1181 err_setstr(RuntimeError, "no such cursor");
1182 return NULL;
1183 }
1184 wsetwincursor(self->w_win, c);
1185 INCREF(None);
1186 return None;
1187}
1188
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001189static struct methodlist window_methods[] = {
1190 {"begindrawing",window_begindrawing},
1191 {"change", window_change},
1192 {"getdocsize", window_getdocsize},
1193 {"getorigin", window_getorigin},
1194 {"gettitle", window_gettitle},
1195 {"getwinsize", window_getwinsize},
1196 {"menucreate", window_menucreate},
1197 {"scroll", window_scroll},
Guido van Rossum5b10f451990-10-30 16:01:48 +00001198 {"setwincursor",window_setwincursor},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001199 {"setdocsize", window_setdocsize},
1200 {"setorigin", window_setorigin},
Guido van Rossum5b10f451990-10-30 16:01:48 +00001201 {"setselection",window_setselection},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001202 {"settimer", window_settimer},
1203 {"settitle", window_settitle},
1204 {"show", window_show},
1205 {"textcreate", window_textcreate},
1206 {NULL, NULL} /* sentinel */
1207};
1208
1209static object *
1210window_getattr(wp, name)
1211 windowobject *wp;
1212 char *name;
1213{
1214 if (wp->w_attr != NULL) {
1215 object *v = dictlookup(wp->w_attr, name);
1216 if (v != NULL) {
1217 INCREF(v);
1218 return v;
1219 }
1220 }
1221 return findmethod(window_methods, (object *)wp, name);
1222}
1223
1224static int
1225window_setattr(wp, name, v)
1226 windowobject *wp;
1227 char *name;
1228 object *v;
1229{
1230 if (wp->w_attr == NULL) {
1231 wp->w_attr = newdictobject();
1232 if (wp->w_attr == NULL)
1233 return -1;
1234 }
1235 if (v == NULL)
1236 return dictremove(wp->w_attr, name);
1237 else
1238 return dictinsert(wp->w_attr, name, v);
1239}
1240
1241static typeobject Windowtype = {
1242 OB_HEAD_INIT(&Typetype)
1243 0, /*ob_size*/
1244 "window", /*tp_name*/
1245 sizeof(windowobject), /*tp_size*/
1246 0, /*tp_itemsize*/
1247 /* methods */
1248 window_dealloc, /*tp_dealloc*/
1249 window_print, /*tp_print*/
1250 window_getattr, /*tp_getattr*/
1251 window_setattr, /*tp_setattr*/
1252 0, /*tp_compare*/
1253 0, /*tp_repr*/
1254};
1255
1256/* Stdwin methods */
1257
1258static object *
1259stdwin_open(sw, args)
1260 object *sw;
1261 object *args;
1262{
1263 int tag;
1264 object *title;
1265 windowobject *wp;
1266 if (!getstrarg(args, &title))
1267 return NULL;
1268 for (tag = 0; tag < MAXNWIN; tag++) {
1269 if (windowlist[tag] == NULL)
1270 break;
1271 }
1272 if (tag >= MAXNWIN)
1273 return err_nomem();
1274 wp = NEWOBJ(windowobject, &Windowtype);
1275 if (wp == NULL)
1276 return NULL;
1277 INCREF(title);
1278 wp->w_title = title;
1279 wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL);
1280 wp->w_attr = NULL;
1281 if (wp->w_win == NULL) {
1282 DECREF(wp);
1283 return NULL;
1284 }
1285 windowlist[tag] = wp;
1286 wsettag(wp->w_win, tag);
1287 return (object *)wp;
1288}
1289
1290static object *
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001291stdwin_get_poll_event(poll, args)
1292 int poll;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001293 object *args;
1294{
1295 EVENT e;
1296 object *v, *w;
1297 if (!getnoarg(args))
1298 return NULL;
1299 if (Drawing != NULL) {
1300 err_setstr(RuntimeError, "cannot getevent() while drawing");
1301 return NULL;
1302 }
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001303/* again: */
1304 if (poll) {
1305 if (!wpollevent(&e)) {
1306 INCREF(None);
1307 return None;
1308 }
1309 }
1310 else
1311 wgetevent(&e);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001312 if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
1313 /* Turn keyboard interrupts into exceptions */
1314 err_set(KeyboardInterrupt);
1315 return NULL;
1316 }
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001317/*
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001318 if (e.window == NULL && (e.type == WE_COMMAND || e.type == WE_CHAR))
1319 goto again;
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001320*/
Guido van Rossum124967c1990-11-06 15:17:35 +00001321 if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) {
1322 /* Turn WC_CLOSE commands into WE_CLOSE events */
1323 e.type = WE_CLOSE;
1324 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001325 v = newtupleobject(3);
1326 if (v == NULL)
1327 return NULL;
1328 if ((w = newintobject((long)e.type)) == NULL) {
1329 DECREF(v);
1330 return NULL;
1331 }
1332 settupleitem(v, 0, w);
1333 if (e.window == NULL)
1334 w = None;
1335 else {
1336 int tag = wgettag(e.window);
1337 if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL)
1338 w = None;
1339 else
1340 w = (object *)windowlist[tag];
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001341#ifdef sgi
1342 /* XXX Trap for unexplained weird bug */
1343 if ((long)w == (long)0x80000001) {
1344 err_setstr(SystemError,
1345 "bad pointer in stdwin.getevent()");
1346 return NULL;
1347 }
1348#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001349 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001350 INCREF(w);
1351 settupleitem(v, 1, w);
1352 switch (e.type) {
1353 case WE_CHAR:
1354 {
1355 char c[1];
1356 c[0] = e.u.character;
1357 w = newsizedstringobject(c, 1);
1358 }
1359 break;
1360 case WE_COMMAND:
1361 w = newintobject((long)e.u.command);
1362 break;
1363 case WE_DRAW:
1364 w = makerect(e.u.area.left, e.u.area.top,
1365 e.u.area.right, e.u.area.bottom);
1366 break;
1367 case WE_MOUSE_DOWN:
1368 case WE_MOUSE_MOVE:
1369 case WE_MOUSE_UP:
1370 w = makemouse(e.u.where.h, e.u.where.v,
1371 e.u.where.clicks,
1372 e.u.where.button,
1373 e.u.where.mask);
1374 break;
1375 case WE_MENU:
1376 if (e.u.m.id >= 0 && e.u.m.id < MAXNMENU &&
1377 menulist[e.u.m.id] != NULL)
1378 w = (object *)menulist[e.u.m.id];
1379 else
1380 w = None;
1381 w = makemenu(w, e.u.m.item);
1382 break;
Guido van Rossum5b10f451990-10-30 16:01:48 +00001383 case WE_LOST_SEL:
1384 w = newintobject((long)e.u.sel);
1385 break;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001386 default:
1387 w = None;
1388 INCREF(w);
1389 break;
1390 }
1391 if (w == NULL) {
1392 DECREF(v);
1393 return NULL;
1394 }
1395 settupleitem(v, 2, w);
1396 return v;
1397}
1398
1399static object *
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001400stdwin_getevent(sw, args)
1401 object *sw;
1402 object *args;
1403{
1404 return stdwin_get_poll_event(0, args);
1405}
1406
1407static object *
1408stdwin_pollevent(sw, args)
1409 object *sw;
1410 object *args;
1411{
1412 return stdwin_get_poll_event(1, args);
1413}
1414
1415static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001416stdwin_setdefwinpos(sw, args)
1417 object *sw;
1418 object *args;
1419{
1420 int a[2];
1421 if (!getpointarg(args, a))
1422 return NULL;
1423 wsetdefwinpos(a[0], a[1]);
1424 INCREF(None);
1425 return None;
1426}
1427
1428static object *
1429stdwin_setdefwinsize(sw, args)
1430 object *sw;
1431 object *args;
1432{
1433 int a[2];
1434 if (!getpointarg(args, a))
1435 return NULL;
1436 wsetdefwinsize(a[0], a[1]);
1437 INCREF(None);
1438 return None;
1439}
1440
1441static object *
Guido van Rossum33f17701991-02-13 23:19:39 +00001442stdwin_getdefwinpos(wp, args)
1443 windowobject *wp;
1444 object *args;
1445{
1446 int h, v;
1447 if (!getnoarg(args))
1448 return NULL;
1449 wgetdefwinpos(&h, &v);
1450 return makepoint(h, v);
1451}
1452
1453static object *
1454stdwin_getdefwinsize(wp, args)
1455 windowobject *wp;
1456 object *args;
1457{
1458 int width, height;
1459 if (!getnoarg(args))
1460 return NULL;
1461 wgetdefwinsize(&width, &height);
1462 return makepoint(width, height);
1463}
1464
1465static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001466stdwin_menucreate(self, args)
1467 object *self;
1468 object *args;
1469{
1470 object *title;
1471 if (!getstrarg(args, &title))
1472 return NULL;
1473 wmenusetdeflocal(0);
1474 return (object *)newmenuobject(title);
1475}
1476
1477static object *
1478stdwin_askfile(self, args)
1479 object *self;
1480 object *args;
1481{
1482 object *prompt, *dflt;
1483 int new, ret;
1484 char buf[256];
1485 if (!getstrstrintarg(args, &prompt, &dflt, &new))
1486 return NULL;
1487 strncpy(buf, getstringvalue(dflt), sizeof buf);
1488 buf[sizeof buf - 1] = '\0';
1489 ret = waskfile(getstringvalue(prompt), buf, sizeof buf, new);
1490 if (!ret) {
1491 err_set(KeyboardInterrupt);
1492 return NULL;
1493 }
1494 return newstringobject(buf);
1495}
1496
1497static object *
1498stdwin_askync(self, args)
1499 object *self;
1500 object *args;
1501{
1502 object *prompt;
1503 int new, ret;
1504 if (!getstrintarg(args, &prompt, &new))
1505 return NULL;
1506 ret = waskync(getstringvalue(prompt), new);
1507 if (ret < 0) {
1508 err_set(KeyboardInterrupt);
1509 return NULL;
1510 }
1511 return newintobject((long)ret);
1512}
1513
1514static object *
1515stdwin_askstr(self, args)
1516 object *self;
1517 object *args;
1518{
1519 object *prompt, *dflt;
1520 int ret;
1521 char buf[256];
1522 if (!getstrstrarg(args, &prompt, &dflt))
1523 return NULL;
1524 strncpy(buf, getstringvalue(dflt), sizeof buf);
1525 buf[sizeof buf - 1] = '\0';
1526 ret = waskstr(getstringvalue(prompt), buf, sizeof buf);
1527 if (!ret) {
1528 err_set(KeyboardInterrupt);
1529 return NULL;
1530 }
1531 return newstringobject(buf);
1532}
1533
1534static object *
1535stdwin_message(self, args)
1536 object *self;
1537 object *args;
1538{
1539 object *msg;
1540 if (!getstrarg(args, &msg))
1541 return NULL;
1542 wmessage(getstringvalue(msg));
1543 INCREF(None);
1544 return None;
1545}
1546
1547static object *
1548stdwin_fleep(self, args)
1549 object *self;
1550 object *args;
1551{
1552 if (!getnoarg(args))
1553 return NULL;
1554 wfleep();
1555 INCREF(None);
1556 return None;
1557}
1558
1559static object *
1560stdwin_setcutbuffer(self, args)
1561 object *self;
1562 object *args;
1563{
Guido van Rossum5b10f451990-10-30 16:01:48 +00001564 int i;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001565 object *str;
Guido van Rossum124967c1990-11-06 15:17:35 +00001566 if (!getintstrarg(args, &i, &str))
1567 return NULL;
Guido van Rossum5b10f451990-10-30 16:01:48 +00001568 wsetcutbuffer(i, getstringvalue(str), getstringsize(str));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001569 INCREF(None);
1570 return None;
1571}
1572
1573static object *
1574stdwin_getcutbuffer(self, args)
1575 object *self;
1576 object *args;
1577{
Guido van Rossum5b10f451990-10-30 16:01:48 +00001578 int i;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001579 char *str;
Guido van Rossum01769f01990-10-30 13:39:00 +00001580 int len;
Guido van Rossum124967c1990-11-06 15:17:35 +00001581 if (!getintarg(args, &i))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001582 return NULL;
Guido van Rossum5b10f451990-10-30 16:01:48 +00001583 str = wgetcutbuffer(i, &len);
Guido van Rossum01769f01990-10-30 13:39:00 +00001584 if (str == NULL) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001585 str = "";
Guido van Rossum01769f01990-10-30 13:39:00 +00001586 len = 0;
1587 }
1588 return newsizedstringobject(str, len);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001589}
1590
Guido van Rossum5b10f451990-10-30 16:01:48 +00001591static object *
1592stdwin_rotatecutbuffers(self, args)
1593 object *self;
1594 object *args;
1595{
1596 int i;
1597 if (!getintarg(args, &i))
1598 return NULL;
1599 wrotatecutbuffers(i);
1600 INCREF(None);
1601 return None;
1602}
1603
1604static object *
1605stdwin_getselection(self, args)
1606 object *self;
1607 object *args;
1608{
1609 int sel;
1610 char *data;
1611 int len;
1612 if (!getintarg(args, &sel))
1613 return NULL;
1614 data = wgetselection(sel, &len);
1615 if (data == NULL) {
1616 data = "";
1617 len = 0;
1618 }
1619 return newsizedstringobject(data, len);
1620}
1621
1622static object *
1623stdwin_resetselection(self, args)
1624 object *self;
1625 object *args;
1626{
1627 int sel;
1628 if (!getintarg(args, &sel))
1629 return NULL;
1630 wresetselection(sel);
1631 INCREF(None);
1632 return None;
1633}
1634
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001635static struct methodlist stdwin_methods[] = {
1636 {"askfile", stdwin_askfile},
1637 {"askstr", stdwin_askstr},
1638 {"askync", stdwin_askync},
1639 {"fleep", stdwin_fleep},
Guido van Rossum5b10f451990-10-30 16:01:48 +00001640 {"getselection", stdwin_getselection},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001641 {"getcutbuffer", stdwin_getcutbuffer},
Guido van Rossum33f17701991-02-13 23:19:39 +00001642 {"getdefwinpos", stdwin_getdefwinpos},
1643 {"getdefwinsize", stdwin_getdefwinsize},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001644 {"getevent", stdwin_getevent},
1645 {"menucreate", stdwin_menucreate},
1646 {"message", stdwin_message},
1647 {"open", stdwin_open},
Guido van Rossume8e7cf41991-01-16 14:06:18 +00001648 {"pollevent", stdwin_pollevent},
Guido van Rossum5b10f451990-10-30 16:01:48 +00001649 {"resetselection", stdwin_resetselection},
1650 {"rotatecutbuffers", stdwin_rotatecutbuffers},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001651 {"setcutbuffer", stdwin_setcutbuffer},
1652 {"setdefwinpos", stdwin_setdefwinpos},
1653 {"setdefwinsize", stdwin_setdefwinsize},
1654
1655 /* Text measuring methods borrow code from drawing objects: */
1656 {"baseline", drawing_baseline},
1657 {"lineheight", drawing_lineheight},
1658 {"textbreak", drawing_textbreak},
1659 {"textwidth", drawing_textwidth},
1660 {NULL, NULL} /* sentinel */
1661};
1662
1663void
1664initstdwin()
1665{
1666 initmodule("stdwin", stdwin_methods);
1667}