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