1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3
4 /*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: See CVS logs. Details at http://www.graphviz.org/
12 *************************************************************************/
13
14 /* Lefteris Koutsofios - AT&T Labs Research */
15
16 #include "common.h"
17 #include "g.h"
18 #include "gcommon.h"
19 #include "mem.h"
20
21 Gwidget_t *Gwidgets;
22 int Gwidgetn;
23
24 Gbitmap_t *Gbitmaps;
25 int Gbitmapn;
26 #define BITMAPINCR 10
27 #define BITMAPSIZE sizeof (Gbitmap_t)
28
29 char *Gdefaultfont;
30 int Gneedredraw;
31 int Gbuttonsdown;
32 int Gerrflag;
33 int Gerrno;
34
35 char *texts;
36 int textn;
37
38 static long wsizes[G_WTYPESIZE];
39 static Gtextline_t tlarray[1000];
40
41 Gwattrmap_t Gwattrmap[] = {
42 { G_ATTRORIGIN, G_ATTRTYPEPOINT, "origin", },
43 { G_ATTRSIZE, G_ATTRTYPESIZE, "size", },
44 { G_ATTRBORDERWIDTH, G_ATTRTYPEINT, "borderwidth", },
45 { G_ATTRNAME, G_ATTRTYPETEXT, "name", },
46 { G_ATTRTEXT, G_ATTRTYPETEXT, "text", },
47 { G_ATTRAPPENDTEXT, G_ATTRTYPETEXT, "appendtext", },
48 { G_ATTRSELECTION, G_ATTRTYPETEXT, "selection", },
49 { G_ATTRCURSOR, G_ATTRTYPETEXT, "cursor", },
50 { G_ATTRMODE, G_ATTRTYPETEXT, "mode", },
51 { G_ATTRLAYOUT, G_ATTRTYPETEXT, "layout", },
52 { G_ATTRZORDER, G_ATTRTYPETEXT, "zorder", },
53 { G_ATTRCOLOR, G_ATTRTYPECOLOR, "color", },
54 { G_ATTRVIEWPORT, G_ATTRTYPESIZE, "viewport", },
55 { G_ATTRWINDOW, G_ATTRTYPERECT, "window", },
56 { G_ATTRWINDOWID, G_ATTRTYPETEXT, "windowid", },
57 { G_ATTRCHILDCENTER, G_ATTRTYPEPOINT, "childcenter", },
58 { G_ATTRNEWLINECB, G_ATTRTYPEFUNC, "newlinecb", },
59 { G_ATTRRESIZECB, G_ATTRTYPEFUNC, "resizecb", },
60 { G_ATTRBUTTONCB, G_ATTRTYPEFUNC, "buttoncb", },
61 { G_ATTREVENTCB, G_ATTRTYPEFUNC, "eventcb", },
62 { G_ATTRUSERDATA, G_ATTRTYPEFUNC, "userdata", },
63 { -1, -1, NULL, },
64 };
65
66 static int arrayattr[] = {
67 G_ATTRSIZE,
68 G_ATTRBORDERWIDTH,
69 G_ATTRMODE,
70 G_ATTRLAYOUT,
71 G_ATTRCOLOR,
72 G_ATTRWINDOWID,
73 G_ATTRRESIZECB,
74 G_ATTRUSERDATA,
75 -1
76 };
77
78 static int buttonattr[] = {
79 G_ATTRSIZE,
80 G_ATTRBORDERWIDTH,
81 G_ATTRTEXT,
82 G_ATTRCOLOR,
83 G_ATTRWINDOWID,
84 G_ATTRBUTTONCB,
85 G_ATTRUSERDATA,
86 -1
87 };
88
89 static int canvasattr[] = {
90 G_ATTRSIZE,
91 G_ATTRBORDERWIDTH,
92 #ifdef FEATURE_GMAP
93 G_ATTRMODE,
94 #endif
95 G_ATTRCURSOR,
96 G_ATTRCOLOR,
97 G_ATTRVIEWPORT,
98 G_ATTRWINDOW,
99 G_ATTRWINDOWID,
100 G_ATTREVENTCB,
101 G_ATTRUSERDATA,
102 -1
103 };
104
105 static int labelattr[] = {
106 G_ATTRSIZE,
107 G_ATTRBORDERWIDTH,
108 G_ATTRTEXT,
109 G_ATTRCOLOR,
110 G_ATTRWINDOWID,
111 G_ATTREVENTCB,
112 G_ATTRUSERDATA,
113 -1
114 };
115
116 static int menuattr[] = {
117 G_ATTRUSERDATA,
118 -1
119 };
120
121 static int pcanvasattr[] = {
122 G_ATTRORIGIN,
123 G_ATTRSIZE,
124 G_ATTRNAME,
125 G_ATTRMODE,
126 G_ATTRCOLOR,
127 G_ATTRWINDOW,
128 G_ATTRWINDOWID,
129 G_ATTREVENTCB,
130 G_ATTRUSERDATA,
131 -1
132 };
133
134 static int queryattr[] = {
135 G_ATTRMODE,
136 G_ATTRUSERDATA,
137 -1
138 };
139
140 static int scrollattr[] = {
141 G_ATTRSIZE,
142 G_ATTRBORDERWIDTH,
143 G_ATTRCHILDCENTER,
144 G_ATTRMODE,
145 G_ATTRCOLOR,
146 G_ATTRWINDOWID,
147 G_ATTRUSERDATA,
148 -1,
149 };
150
151 static int textattr[] = {
152 G_ATTRSIZE,
153 G_ATTRBORDERWIDTH,
154 G_ATTRTEXT,
155 G_ATTRAPPENDTEXT,
156 G_ATTRSELECTION,
157 G_ATTRMODE,
158 G_ATTRCOLOR,
159 G_ATTRWINDOWID,
160 G_ATTRNEWLINECB,
161 G_ATTRUSERDATA,
162 -1
163 };
164
165 static int viewattr[] = {
166 G_ATTRORIGIN,
167 G_ATTRSIZE,
168 G_ATTRNAME,
169 G_ATTRCOLOR,
170 G_ATTRZORDER,
171 G_ATTRWINDOWID,
172 G_ATTREVENTCB,
173 G_ATTRUSERDATA,
174 -1
175 };
176
177 Gwlist_t Gwlist[] = {
178 { G_ARRAYWIDGET, "array", &arrayattr[0], },
179 { G_BUTTONWIDGET, "button", &buttonattr[0], },
180 { G_CANVASWIDGET, "canvas", &canvasattr[0], },
181 { G_LABELWIDGET, "label", &labelattr[0], },
182 { G_MENUWIDGET, "menu", &menuattr[0], },
183 { G_PCANVASWIDGET, "ps", &pcanvasattr[0], },
184 { G_QUERYWIDGET, "query", &queryattr[0], },
185 { G_SCROLLWIDGET, "scroll", &scrollattr[0], },
186 { G_TEXTWIDGET, "text", &textattr[0], },
187 { G_VIEWWIDGET, "view", &viewattr[0], },
188 { -1, NULL, NULL, },
189 };
190
191 static char *errmsg[] = {
192 /* Gerrno starts at 1 */ "no error",
193 /* G_ERRBADATTRID */ "bad attribute id %d",
194 /* G_ERRBADATTRVALUE */ "bad attribute value %s",
195 /* G_ERRBADCOLORINDEX */ "bad color index %d",
196 /* G_ERRBADPARENTWIDGETID */ "bad parent widget id %d",
197 /* G_ERRBADWIDGETID */ "bad widget id %d",
198 /* G_ERRBADWIDGETTYPE */ "bad widget type %d",
199 /* G_ERRCANNOTCREATEWIDGET */ "cannot create widget",
200 /* G_ERRCANNOTGETATTR */ "cannot get attribute %s",
201 /* G_ERRCANNOTOPENFILE */ "cannot open file %s",
202 /* G_ERRCANNOTSETATTR1 */ "cannot set attribute %s in createwidget",
203 /* G_ERRCANNOTSETATTR2 */ "cannot set attribute %s in setwidgetattr",
204 /* G_ERRINITFAILED */ "initialization failed",
205 /* G_ERRNOCHILDWIDGET */ "no child widget",
206 /* G_ERRNOPARENTWIDGET */ "no parent widget",
207 /* G_ERRNOSUCHCURSOR */ "no such cursor %s",
208 /* G_ERRNOTACANVAS */ "widget %d is not a canvas",
209 /* G_ERRNOTIMPLEMENTED */ "not implemented",
210 /* G_ERRNOTSUPPORTED */ "not supported",
211 /* G_ERRBADBITMAPID */ "bad bitmap id %d",
212 /* G_ERRCANNOTCREATEBITMAP */ "cannot create bitmap",
213 /* G_ERRNOBITMAP */ "no bitmap",
214 /* G_ERRCANNOTREADBITMAP */ "cannot read bitmap",
215 };
216
217 static int unpackstring (char *);
218
Ginit(void)219 int Ginit (void) {
220 int wi, bi;
221
222 wsizes[G_ARRAYWIDGET] = AWSIZE;
223 wsizes[G_BUTTONWIDGET] = BWSIZE;
224 wsizes[G_CANVASWIDGET] = CWSIZE;
225 wsizes[G_LABELWIDGET] = LWSIZE;
226 wsizes[G_MENUWIDGET] = MWSIZE;
227 wsizes[G_PCANVASWIDGET] = PWSIZE;
228 wsizes[G_QUERYWIDGET] = QWSIZE;
229 wsizes[G_SCROLLWIDGET] = SWSIZE;
230 wsizes[G_TEXTWIDGET] = TWSIZE;
231 wsizes[G_VIEWWIDGET] = VWSIZE;
232 Gwidgets = Marrayalloc ((long) WIDGETINCR * WIDGETSIZE);
233 Gwidgetn = WIDGETINCR;
234 for (wi = 0; wi < Gwidgetn; wi++)
235 Gwidgets[wi].inuse = FALSE;
236 Gbitmapn = BITMAPINCR;
237 Gbitmaps = Marrayalloc ((long) Gbitmapn * BITMAPSIZE);
238 for (bi = 0; bi < Gbitmapn; bi++)
239 Gbitmaps[bi].inuse = FALSE;
240 Gneedredraw = FALSE;
241 Gbuttonsdown = 0;
242 Gdefaultfont = "";
243 Gerrflag = FALSE;
244 textn = 100;
245 texts = Marrayalloc ((long) textn);
246 texts[0] = '\0';
247 Ginitgraphics ();
248 return 0;
249 }
250
Gterm(void)251 int Gterm (void) {
252 int wi;
253
254 for (wi = 0; wi < Gwidgetn; wi++)
255 if (Gwidgets[wi].inuse)
256 Gdestroywidget (wi);
257 Gtermgraphics ();
258 Marrayfree (texts), texts = NULL, textn = 0;
259 Marrayfree (Gwidgets), Gwidgets = NULL, Gwidgetn = 0;
260 Marrayfree (Gbitmaps), Gbitmaps = NULL, Gbitmapn = 0;
261 return 0;
262 }
263
Gcreatewidget(int pwi,int type,int attrn,Gwattr_t * attrp)264 int Gcreatewidget (int pwi, int type, int attrn, Gwattr_t *attrp) {
265 Gwidget_t *parent, *widget;
266 int rtn;
267
268 if ((pwi != -1) && (pwi < 0 || pwi > Gwidgetn || !Gwidgets[pwi].inuse)) {
269 Gerr (POS, G_ERRBADPARENTWIDGETID, pwi);
270 return -1;
271 }
272 if (type < 0 || type >= G_WTYPESIZE) {
273 Gerr (POS, G_ERRBADWIDGETTYPE, type);
274 return -1;
275 }
276 widget = newwidget (type);
277 widget->inuse = TRUE;
278 widget->pwi = pwi;
279 parent = (pwi == -1) ? NULL : &Gwidgets[pwi];
280 rtn = -1;
281 switch (type) {
282 case G_ARRAYWIDGET:
283 rtn = GAcreatewidget (parent, widget, attrn, attrp);
284 break;
285 case G_BUTTONWIDGET:
286 rtn = GBcreatewidget (parent, widget, attrn, attrp);
287 break;
288 case G_CANVASWIDGET:
289 rtn = GCcreatewidget (parent, widget, attrn, attrp);
290 break;
291 case G_LABELWIDGET:
292 rtn = GLcreatewidget (parent, widget, attrn, attrp);
293 break;
294 case G_MENUWIDGET:
295 rtn = GMcreatewidget (parent, widget, attrn, attrp);
296 break;
297 case G_PCANVASWIDGET:
298 rtn = GPcreatewidget (parent, widget, attrn, attrp);
299 break;
300 case G_QUERYWIDGET:
301 rtn = GQcreatewidget (parent, widget, attrn, attrp);
302 break;
303 case G_SCROLLWIDGET:
304 rtn = GScreatewidget (parent, widget, attrn, attrp);
305 break;
306 case G_TEXTWIDGET:
307 rtn = GTcreatewidget (parent, widget, attrn, attrp);
308 break;
309 case G_VIEWWIDGET:
310 rtn = GVcreatewidget (parent, widget, attrn, attrp);
311 break;
312 }
313 if (rtn == -1) {
314 widget->inuse = FALSE;
315 return -1;
316 }
317 return widget - &Gwidgets[0];
318 }
319
Gsetwidgetattr(int wi,int attrn,Gwattr_t * attrp)320 int Gsetwidgetattr (int wi, int attrn, Gwattr_t *attrp) {
321 Gwidget_t *widget;
322
323 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
324 Gerr (POS, G_ERRBADWIDGETID, wi);
325 return -1;
326 }
327 widget = &Gwidgets[wi];
328 switch (widget->type) {
329 case G_ARRAYWIDGET: return GAsetwidgetattr (widget, attrn, attrp);
330 case G_BUTTONWIDGET: return GBsetwidgetattr (widget, attrn, attrp);
331 case G_CANVASWIDGET: return GCsetwidgetattr (widget, attrn, attrp);
332 case G_LABELWIDGET: return GLsetwidgetattr (widget, attrn, attrp);
333 case G_MENUWIDGET: return GMsetwidgetattr (widget, attrn, attrp);
334 case G_PCANVASWIDGET: return GPsetwidgetattr (widget, attrn, attrp);
335 case G_QUERYWIDGET: return GQsetwidgetattr (widget, attrn, attrp);
336 case G_SCROLLWIDGET: return GSsetwidgetattr (widget, attrn, attrp);
337 case G_TEXTWIDGET: return GTsetwidgetattr (widget, attrn, attrp);
338 case G_VIEWWIDGET: return GVsetwidgetattr (widget, attrn, attrp);
339 }
340 return -1;
341 }
342
Ggetwidgetattr(int wi,int attrn,Gwattr_t * attrp)343 int Ggetwidgetattr (int wi, int attrn, Gwattr_t *attrp) {
344 Gwidget_t *widget;
345
346 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
347 Gerr (POS, G_ERRBADWIDGETID, wi);
348 return -1;
349 }
350 widget = &Gwidgets[wi];
351 switch (widget->type) {
352 case G_ARRAYWIDGET: return GAgetwidgetattr (widget, attrn, attrp);
353 case G_BUTTONWIDGET: return GBgetwidgetattr (widget, attrn, attrp);
354 case G_CANVASWIDGET: return GCgetwidgetattr (widget, attrn, attrp);
355 case G_LABELWIDGET: return GLgetwidgetattr (widget, attrn, attrp);
356 case G_MENUWIDGET: return GMgetwidgetattr (widget, attrn, attrp);
357 case G_PCANVASWIDGET: return GPgetwidgetattr (widget, attrn, attrp);
358 case G_QUERYWIDGET: return GQgetwidgetattr (widget, attrn, attrp);
359 case G_SCROLLWIDGET: return GSgetwidgetattr (widget, attrn, attrp);
360 case G_TEXTWIDGET: return GTgetwidgetattr (widget, attrn, attrp);
361 case G_VIEWWIDGET: return GVgetwidgetattr (widget, attrn, attrp);
362 }
363 return -1;
364 }
365
Gdestroywidget(int wi)366 int Gdestroywidget (int wi) {
367 Gwidget_t *widget;
368
369 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
370 Gerr (POS, G_ERRBADWIDGETID, wi);
371 return -1;
372 }
373 widget = &Gwidgets[wi];
374 switch (widget->type) {
375 case G_ARRAYWIDGET: GAdestroywidget (widget); break;
376 case G_BUTTONWIDGET: GBdestroywidget (widget); break;
377 case G_CANVASWIDGET: GCdestroywidget (widget); break;
378 case G_LABELWIDGET: GLdestroywidget (widget); break;
379 case G_MENUWIDGET: GMdestroywidget (widget); break;
380 case G_PCANVASWIDGET: GPdestroywidget (widget); break;
381 case G_QUERYWIDGET: GQdestroywidget (widget); break;
382 case G_SCROLLWIDGET: GSdestroywidget (widget); break;
383 case G_TEXTWIDGET: GTdestroywidget (widget); break;
384 case G_VIEWWIDGET: GVdestroywidget (widget); break;
385 }
386 /* HACK: should do switch on type ... */
387 free (widget->u.c);
388 widget->inuse = FALSE;
389 return 0;
390 }
391
Gqueryask(int wi,char * prompt,char * args,char * responsep,int responsen)392 int Gqueryask (
393 int wi, char *prompt, char *args, char *responsep, int responsen
394 ) {
395 Gwidget_t *widget;
396
397 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
398 Gerr (POS, G_ERRBADWIDGETID, wi);
399 return -1;
400 }
401 widget = &Gwidgets[wi];
402 return GQqueryask (widget, prompt, args, responsep, responsen);
403 }
404
Gmenuaddentries(int wi,int en,char ** ep)405 int Gmenuaddentries (int wi, int en, char **ep) {
406 Gwidget_t *widget;
407
408 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
409 Gerr (POS, G_ERRBADWIDGETID, wi);
410 return -1;
411 }
412 widget = &Gwidgets[wi];
413 return GMmenuaddentries (widget, en, ep);
414 }
415
Gmenudisplay(int pwi,int wi)416 int Gmenudisplay (int pwi, int wi) {
417 Gwidget_t *parent, *widget;
418
419 if (pwi < 0 || pwi > Gwidgetn || !Gwidgets[pwi].inuse) {
420 Gerr (POS, G_ERRBADPARENTWIDGETID, wi);
421 return -1;
422 }
423 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
424 Gerr (POS, G_ERRBADWIDGETID, wi);
425 return -1;
426 }
427 parent = &Gwidgets[pwi];
428 widget = &Gwidgets[wi];
429 return GMmenudisplay (parent, widget);
430 }
431
432 /* functions for drawing on canvas and pcanvas widgets */
433
Gcanvasclear(int wi)434 int Gcanvasclear (int wi) {
435 Gwidget_t *widget;
436
437 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
438 Gerr (POS, G_ERRBADWIDGETID, wi);
439 return -1;
440 }
441 widget = &Gwidgets[wi];
442 switch (widget->type) {
443 case G_CANVASWIDGET: return GCcanvasclear (widget);
444 case G_PCANVASWIDGET: return GPcanvasclear (widget);
445 }
446 Gerr (POS, G_ERRNOTACANVAS, wi);
447 return -1;
448 }
449
Gsetgfxattr(int wi,Ggattr_t * ap)450 int Gsetgfxattr (int wi, Ggattr_t *ap) {
451 Gwidget_t *widget;
452
453 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
454 Gerr (POS, G_ERRBADWIDGETID, wi);
455 return -1;
456 }
457 widget = &Gwidgets[wi];
458 switch (widget->type) {
459 case G_CANVASWIDGET: return GCsetgfxattr (widget, ap);
460 case G_PCANVASWIDGET: return GPsetgfxattr (widget, ap);
461 }
462 Gerr (POS, G_ERRNOTACANVAS, wi);
463 return -1;
464 }
465
Ggetgfxattr(int wi,Ggattr_t * ap)466 int Ggetgfxattr (int wi, Ggattr_t *ap) {
467 Gwidget_t *widget;
468
469 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
470 Gerr (POS, G_ERRBADWIDGETID, wi);
471 return -1;
472 }
473 widget = &Gwidgets[wi];
474 switch (widget->type) {
475 case G_CANVASWIDGET: return GCgetgfxattr (widget, ap);
476 case G_PCANVASWIDGET: return GPgetgfxattr (widget, ap);
477 }
478 Gerr (POS, G_ERRNOTACANVAS, wi);
479 return -1;
480 }
481
Garrow(int wi,Gpoint_t gp1,Gpoint_t gp2,Ggattr_t * ap)482 int Garrow (int wi, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
483 Gwidget_t *widget;
484
485 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
486 Gerr (POS, G_ERRBADWIDGETID, wi);
487 return -1;
488 }
489 widget = &Gwidgets[wi];
490 switch (widget->type) {
491 case G_CANVASWIDGET: return GCarrow (widget, gp1, gp2, ap);
492 case G_PCANVASWIDGET: return GParrow (widget, gp1, gp2, ap);
493 }
494 Gerr (POS, G_ERRNOTACANVAS, wi);
495 return -1;
496 }
497
Gline(int wi,Gpoint_t gp1,Gpoint_t gp2,Ggattr_t * ap)498 int Gline (int wi, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
499 Gwidget_t *widget;
500
501 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
502 Gerr (POS, G_ERRBADWIDGETID, wi);
503 return -1;
504 }
505 widget = &Gwidgets[wi];
506 switch (widget->type) {
507 case G_CANVASWIDGET: return GCline (widget, gp1, gp2, ap);
508 case G_PCANVASWIDGET: return GPline (widget, gp1, gp2, ap);
509 }
510 Gerr (POS, G_ERRNOTACANVAS, wi);
511 return -1;
512 }
513
Gbox(int wi,Grect_t gr,Ggattr_t * ap)514 int Gbox (int wi, Grect_t gr, Ggattr_t *ap) {
515 Gwidget_t *widget;
516
517 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
518 Gerr (POS, G_ERRBADWIDGETID, wi);
519 return -1;
520 }
521 widget = &Gwidgets[wi];
522 switch (widget->type) {
523 case G_CANVASWIDGET: return GCbox (widget, gr, ap);
524 case G_PCANVASWIDGET: return GPbox (widget, gr, ap);
525 }
526 Gerr (POS, G_ERRNOTACANVAS, wi);
527 return -1;
528 }
529
Gpolygon(int wi,int gpn,Gpoint_t * gpp,Ggattr_t * ap)530 int Gpolygon (int wi, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
531 Gwidget_t *widget;
532
533 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
534 Gerr (POS, G_ERRBADWIDGETID, wi);
535 return -1;
536 }
537 widget = &Gwidgets[wi];
538 switch (widget->type) {
539 case G_CANVASWIDGET: return GCpolygon (widget, gpn, gpp, ap);
540 case G_PCANVASWIDGET: return GPpolygon (widget, gpn, gpp, ap);
541 }
542 Gerr (POS, G_ERRNOTACANVAS, wi);
543 return -1;
544 }
545
Gsplinegon(int wi,int gpn,Gpoint_t * gpp,Ggattr_t * ap)546 int Gsplinegon (int wi, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
547 Gwidget_t *widget;
548
549 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
550 Gerr (POS, G_ERRBADWIDGETID, wi);
551 return -1;
552 }
553 widget = &Gwidgets[wi];
554 switch (widget->type) {
555 case G_CANVASWIDGET: return GCsplinegon (widget, gpn, gpp, ap);
556 case G_PCANVASWIDGET: return GPsplinegon (widget, gpn, gpp, ap);
557 }
558 Gerr (POS, G_ERRNOTACANVAS, wi);
559 return -1;
560 }
561
Garc(int wi,Gpoint_t gc,Gsize_t gs,double ang1,double ang2,Ggattr_t * ap)562 int Garc (
563 int wi, Gpoint_t gc, Gsize_t gs, double ang1, double ang2, Ggattr_t *ap
564 ) {
565 Gwidget_t *widget;
566
567 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
568 Gerr (POS, G_ERRBADWIDGETID, wi);
569 return -1;
570 }
571 widget = &Gwidgets[wi];
572 switch (widget->type) {
573 case G_CANVASWIDGET: return GCarc (widget, gc, gs, ang1, ang2, ap);
574 case G_PCANVASWIDGET: return GParc (widget, gc, gs, ang1, ang2, ap);
575 }
576 Gerr (POS, G_ERRNOTACANVAS, wi);
577 return -1;
578 }
579
Gtext(int wi,char * string,Gpoint_t go,char * fn,double fs,char * justs,Ggattr_t * ap)580 int Gtext (
581 int wi, char *string, Gpoint_t go, char *fn, double fs,
582 char *justs, Ggattr_t *ap
583 ) {
584 Gwidget_t *widget;
585 char js[2];
586 int n;
587
588 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
589 Gerr (POS, G_ERRBADWIDGETID, wi);
590 return -1;
591 }
592 widget = &Gwidgets[wi];
593 if (string[0] == '\000')
594 return 0;
595 n = unpackstring (string);
596 if (!justs[0] || !justs[1])
597 js[0] = 'c', js[1] = 'c';
598 else {
599 js[0] = justs[0], js[1] = justs[1];
600 if (js[0] != 'l' && js[0] != 'c' && js[0] != 'r')
601 js[0] = 'c';
602 if (js[1] != 'd' && js[1] != 'b' && js[1] != 'c' && js[1] != 'u')
603 js[1] = 'c';
604 }
605 switch (widget->type) {
606 case G_CANVASWIDGET:
607 return GCtext (widget, &tlarray[0], n, go, fn, fs, &js[0], ap);
608 case G_PCANVASWIDGET:
609 return GPtext (widget, &tlarray[0], n, go, fn, fs, &js[0], ap);
610 }
611 Gerr (POS, G_ERRNOTACANVAS, wi);
612 return -1;
613 }
614
Ggettextsize(int wi,char * string,char * fn,double fs,Gsize_t * gsp)615 int Ggettextsize (int wi, char *string, char *fn, double fs, Gsize_t *gsp) {
616 Gwidget_t *widget;
617 int n;
618
619 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
620 Gerr (POS, G_ERRBADWIDGETID, wi);
621 return -1;
622 }
623 widget = &Gwidgets[wi];
624 if (widget->type != G_CANVASWIDGET) {
625 Gerr (POS, G_ERRNOTACANVAS, wi);
626 return -1;
627 }
628 if (string[0] == '\000') {
629 gsp->x = gsp->y = 0.0;
630 return 0;
631 }
632 n = unpackstring (string);
633 return GCgettextsize (widget, &tlarray[0], n, fn, fs, gsp);
634 }
635
Gcreatebitmap(int wi,Gsize_t s)636 int Gcreatebitmap (int wi, Gsize_t s) {
637 Gwidget_t *widget;
638 Gbitmap_t *bitmap;
639 int rtn;
640
641 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
642 Gerr (POS, G_ERRBADPARENTWIDGETID, wi);
643 return -1;
644 }
645 widget = &Gwidgets[wi];
646 if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
647 Gerr (POS, G_ERRNOTACANVAS, wi);
648 return -1;
649 }
650 bitmap = newbitmap ();
651 bitmap->inuse = TRUE;
652 bitmap->canvas = wi;
653 rtn = -1;
654 switch (widget->type) {
655 case G_CANVASWIDGET: rtn = GCcreatebitmap (widget, bitmap, s); break;
656 case G_PCANVASWIDGET: rtn = GPcreatebitmap (widget, bitmap, s); break;
657 }
658 if (rtn == -1) {
659 bitmap->inuse = FALSE;
660 return -1;
661 }
662 return bitmap - &Gbitmaps[0];
663 }
664
Gdestroybitmap(int bi)665 int Gdestroybitmap (int bi) {
666 Gbitmap_t *bitmap;
667
668 if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
669 Gerr (POS, G_ERRBADBITMAPID, bi);
670 return -1;
671 }
672 bitmap = &Gbitmaps[bi];
673 switch (bitmap->ctype) {
674 case G_CANVASWIDGET: GCdestroybitmap (bitmap); break;
675 case G_PCANVASWIDGET: GPdestroybitmap (bitmap); break;
676 }
677 bitmap->inuse = FALSE;
678 return 0;
679 }
680
Greadbitmap(int wi,FILE * fp)681 int Greadbitmap (int wi, FILE *fp) {
682 Gwidget_t *widget;
683 Gbitmap_t *bitmap;
684 int rtn;
685
686 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
687 Gerr (POS, G_ERRBADPARENTWIDGETID, wi);
688 return -1;
689 }
690 widget = &Gwidgets[wi];
691 if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
692 Gerr (POS, G_ERRNOTACANVAS, wi);
693 return -1;
694 }
695 bitmap = newbitmap ();
696 bitmap->inuse = TRUE;
697 bitmap->canvas = wi;
698 rtn = -1;
699 switch (widget->type) {
700 case G_CANVASWIDGET: rtn = GCreadbitmap (widget, bitmap, fp); break;
701 case G_PCANVASWIDGET: rtn = GPreadbitmap (widget, bitmap, fp); break;
702 }
703 if (rtn == -1) {
704 bitmap->inuse = FALSE;
705 return -1;
706 }
707 return bitmap - &Gbitmaps[0];
708 }
709
Gwritebitmap(FILE * fp,int bi)710 int Gwritebitmap (FILE *fp, int bi) {
711 Gbitmap_t *bitmap;
712 int rtn;
713
714 if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
715 Gerr (POS, G_ERRBADBITMAPID, bi);
716 return -1;
717 }
718 bitmap = &Gbitmaps[bi];
719 rtn = -1;
720 switch (bitmap->ctype) {
721 case G_CANVASWIDGET: rtn = GCwritebitmap (bitmap, fp); break;
722 case G_PCANVASWIDGET: rtn = GPwritebitmap (bitmap, fp); break;
723 }
724 if (rtn == -1)
725 return -1;
726 return 0;
727 }
728
Gbitblt(int wi,Gpoint_t gp,Grect_t gr,int bi,char * mode,Ggattr_t * ap)729 int Gbitblt (
730 int wi, Gpoint_t gp, Grect_t gr, int bi, char *mode, Ggattr_t *ap
731 ) {
732 Gwidget_t *widget;
733 Gbitmap_t *bitmap;
734
735 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
736 Gerr (POS, G_ERRBADWIDGETID, wi);
737 return -1;
738 }
739 widget = &Gwidgets[wi];
740 if (bi < 0 || bi > Gbitmapn || !Gbitmaps[bi].inuse) {
741 Gerr (POS, G_ERRBADBITMAPID, bi);
742 return -1;
743 }
744 bitmap = &Gbitmaps[bi];
745 switch (widget->type) {
746 case G_CANVASWIDGET: return GCbitblt (widget, gp, gr, bitmap, mode, ap);
747 case G_PCANVASWIDGET: return GPbitblt (widget, gp, gr, bitmap, mode, ap);
748 }
749 Gerr (POS, G_ERRNOTACANVAS, wi);
750 return -1;
751 }
752
Ggetmousecoords(int wi,Gpoint_t * gsp,int * count)753 int Ggetmousecoords (int wi, Gpoint_t *gsp, int *count) {
754 Gwidget_t *widget;
755
756 if (wi < 0 || wi > Gwidgetn || !Gwidgets[wi].inuse) {
757 Gerr (POS, G_ERRBADWIDGETID, wi);
758 return -1;
759 }
760 widget = &Gwidgets[wi];
761 if (widget->type != G_CANVASWIDGET) {
762 Gerr (POS, G_ERRNOTACANVAS, wi);
763 return -1;
764 }
765 return GCgetmousecoords (widget, gsp, count);
766 }
767
newwidget(int type)768 Gwidget_t *newwidget (int type) {
769 Gwidget_t *new;
770 int wi;
771
772 for (wi = 0; wi < Gwidgetn; wi++)
773 if (!Gwidgets[wi].inuse)
774 goto found;
775
776 Gwidgets = Marraygrow (
777 Gwidgets, (long) (Gwidgetn + WIDGETINCR) * WIDGETSIZE
778 );
779 for (wi = Gwidgetn; wi < Gwidgetn + WIDGETINCR; wi++)
780 Gwidgets[wi].inuse = FALSE;
781 wi = Gwidgetn, Gwidgetn += WIDGETINCR;
782
783 found:
784 new = &Gwidgets[wi];
785 new->type = type;
786 new->w = 0;
787 new->udata = 0;
788 /* HACK: should do a switch on type, but ... */
789 if (!(new->u.c = (Gcw_t *) malloc (wsizes[type])))
790 panic1 (POS, "newwidget", "cannot allocate data");
791 return new;
792 }
793
findwidget(uint64_t w,int type)794 Gwidget_t *findwidget (uint64_t w, int type) {
795 int wi;
796
797 if (type == G_WTYPESIZE) {
798 for (wi = 0; wi < Gwidgetn; wi++)
799 if (Gwidgets[wi].inuse && (uint64_t) Gwidgets[wi].w == w)
800 return &Gwidgets[wi];
801 } else {
802 for (wi = 0; wi < Gwidgetn; wi++)
803 if (
804 Gwidgets[wi].inuse && Gwidgets[wi].type == type &&
805 (uint64_t) Gwidgets[wi].w == w
806 )
807 return &Gwidgets[wi];
808 }
809 return NULL;
810 }
811
newbitmap(void)812 Gbitmap_t *newbitmap (void) {
813 Gbitmap_t *new;
814 int bi;
815
816 for (bi = 0; bi < Gbitmapn; bi++)
817 if (!Gbitmaps[bi].inuse)
818 goto found;
819
820 Gbitmaps = Marraygrow (
821 Gbitmaps, (long) (Gbitmapn + BITMAPINCR) * BITMAPSIZE
822 );
823 for (bi = Gbitmapn; bi < Gbitmapn + BITMAPINCR; bi++)
824 Gbitmaps[bi].inuse = FALSE;
825 bi = Gbitmapn, Gbitmapn += BITMAPINCR;
826
827 found:
828 new = &Gbitmaps[bi];
829 return new;
830 }
831
Gerr(char * file,int line,int errnum,...)832 void Gerr (char *file, int line, int errnum, ...) {
833 va_list args;
834
835 #ifdef FEATURE_X11
836 Gerrno = errnum;
837 if (!Gerrflag)
838 return;
839
840 va_start(args, errnum);
841 fprintf (stderr, "warning: (file %s, line %d) ", file, line);
842 vfprintf (stderr, errmsg[errnum], args);
843 fprintf (stderr, "\n");
844 va_end(args);
845 #else
846 #ifdef FEATURE_WIN32
847 char buf[256];
848
849 Gerrno = errnum;
850 if (!warnflag)
851 return;
852
853 va_start(args, errnum);
854 vsprintf (buf, errmsg[errnum], args);
855 Gnocallbacks = TRUE;
856 MessageBox ((HWND) NULL, buf, "Lefty Warning", MB_APPLMODAL);
857 Gnocallbacks = FALSE;
858 va_end(args);
859 #endif
860 #endif
861 }
862
unpackstring(char * s)863 static int unpackstring (char *s) {
864 char *p1, *p2;
865 int n;
866
867 if ((n = strlen (s) + 1) > textn)
868 textn = n, texts = Marraygrow (texts, (long) textn);
869 strcpy (texts, s);
870 n = 0;
871 p1 = p2 = texts;
872 tlarray[0].p = p1;
873 while (*p1) {
874 if (p1[0] == '\\') {
875 if (p1[1] == 'n' || p1[1] == 'l' || p1[1] == 'r') {
876 tlarray[n].n = p1 - tlarray[n].p;
877 tlarray[n].j = p1[1];
878 tlarray[++n].p = (p1 += 2);
879 } else {
880 for (p2 = p1 + 1; *p2; p2++)
881 p2[-1] = p2[0];
882 p2[-1] = 0;
883 p1++;
884 }
885 } else
886 p1++;
887 }
888 if ((tlarray[n].n = p1 - tlarray[n].p) > 0)
889 tlarray[n++].j = 'n';
890 return n;
891 }
892