1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/ui/RCS/gadgets.c $
21  * $Revision: 1.44 $
22  * $Author: kaboom $
23  * $Date: 1994/08/10 18:43:13 $
24  */
25 
26 // Source code to implement all these goofy gadgets
27 // using the region system.
28 
29 #include <string.h>
30 #include <stdio.h>
31 
32 #include "lg.h"
33 #include "gadgets.h"
34 #include "event.h"
35 #include "mouse.h"
36 #include "2d.h"
37 #include "dbg.h"
38 //#include <_ui.h>
39 #include "rect.h"
40 #include "error.h"
41 #include "kbcook.h"
42 #include "2dres.h"
43 //#include <lgsprntf.h>
44 
45 
46 //---------------------------------------------------------------
47 // Defines and Globals
48 //---------------------------------------------------------------
49 #define NUM_RESOURCE_FILES 1
50 
51 uchar gadget_initialization  = FALSE;
52 uchar initialize_2d = FALSE;
53 
54 
55 //---------------------------------------------------------------
56 // Internal Prototypes
57 //---------------------------------------------------------------
58 errtype draw_resource_bm(Ref id, int x, int y);
59 errtype gad_Mac_init(Gadget *g, LGPoint extent);
60 uchar gad_Mac_blank_expose(LGRegion *reg, LGRect *r);
61 errtype gadget_initialize_system(void);
62 uchar gadget_frob_canvas(LGRegion *reg, void *data);
63 uchar gadget_tng_mouse_move_handler(uiEvent *e, LGRegion *r, intptr_t state);
64 
65 
66 //---------------------------------------------------------------
67 // Device-Specific Stuff
68 //---------------------------------------------------------------
69 // For Mac version: Set up graphics for Mac screen.
70 
71 /*
72 errtype gad_vga_init(Gadget *g, LGPoint extent)
73 {
74 //   grs_screen *screen;
75 
76    // Spew(DSRC_UI_Gadget, ("GAD_VGA_INIT!! %s, (%d, %d)\n",GD_NAME(g->rep), extent.x, extent.y));
77    if (!initialize_2d)
78    {
79 #ifdef WOW_WHAT_A_TOTAL_HACK
80       gr_init();
81       gr_set_mode(GRM_320X200X8, TRUE);
82       screen = gr_alloc_screen(extent.x,extent.y);
83       gr_set_screen(screen);
84 #endif
85       initialize_2d = TRUE;
86    }
87    g->device_data = (grs_canvas *)Malloc(sizeof(grs_canvas));
88    gr_init_sub_canvas(dr_scr_canv, g->device_data, 0, 0, extent.x, extent.y);
89    return (OK);
90 }
91 
92 errtype gad_modex_init(Gadget *g, LGPoint extent)
93 {
94    grs_screen *screen;
95 
96    // Spew(DSRC_UI_Gadget, ("GAD_MODEX_INIT!! %s, (%d, %d)\n",GD_NAME(g->rep), extent.x, extent.y));
97    if (!initialize_2d)
98    {
99       gr_init();
100       gr_set_mode(GRM_320X200X8, TRUE);
101       screen = gr_alloc_screen(extent.x,extent.y);
102       gr_set_screen(screen);
103       initialize_2d = TRUE;
104    }
105 
106    g->device_data = (grs_canvas *)Malloc(sizeof(grs_canvas));
107    gr_init_sub_canvas(dr_scr_canv, g->device_data, 0, 0, extent.x, extent.y);
108    return (OK);
109 }
110 
111 errtype gad_svga_init(Gadget *g, LGPoint extent)
112 {
113    grs_screen *screen;
114 
115    // Spew(DSRC_UI_Gadget, ("GAD_VGA_INIT!! %s, (%d, %d)\n",GD_NAME(g->rep), extent.x, extent.y));
116    if (!initialize_2d)
117    {
118       gr_init();
119       gr_set_mode(GRM_320X200X8, TRUE);
120       screen = gr_alloc_screen(extent.x,extent.y);
121       gr_set_screen(screen);
122       initialize_2d = TRUE;
123    }
124 
125    g->device_data = (grs_canvas *)Malloc(sizeof(grs_canvas));
126    gr_init_sub_canvas(dr_scr_canv, g->device_data, 0, 0, extent.x, extent.y);
127    return (OK);
128 }
129 
130 errtype gad_mono_init(Gadget *g, LGPoint extent)
131 {
132    Gadget *dummy;
133    LGPoint dummy2;
134    dummy = g; dummy2 = extent;
135 
136    return (OK);
137 }
138 */
139 
gad_Mac_init(Gadget * g,LGPoint extent)140 errtype gad_Mac_init(Gadget *g, LGPoint extent)
141 {
142 	grs_screen *screen;
143 
144 	if (!initialize_2d)
145 	{
146 		gr_init();
147 		gr_set_mode(GRM_640x480x8, TRUE);
148 		screen = gr_alloc_screen(extent.x,extent.y);
149 		gr_set_screen(screen);
150 		initialize_2d = TRUE;
151 	}
152 
153 	g->device_data = (grs_canvas *)malloc(sizeof(grs_canvas));
154 	gr_init_sub_canvas(dr_scr_canv, (grs_canvas *)g->device_data, 0, 0, extent.x, extent.y);
155 	return (OK);
156 }
157 
158 /*
159 uchar gad_vga_blank_expose(LGRegion *reg, LGRect *r)
160 {
161    LGRect nrect;
162 
163    region_abs_rect(reg, r, &nrect);
164    SCALE_RECT(&nrect, GD_GADG(reg)->conversion);
165    // Spew(DSRC_UI_Gadget, ("GAD_VGA_BLANK_EXPOSE!! %s, (%d, %d)(%d, %d)\n",GD_NAME(reg), RECT_EXPAND_ARGS(&nrect)));
166    if (GD_CANV(reg) == NULL)
167       // Spew(DSRC_UI_Gadget, ("Perhaps we have a problem here...\n"));
168    gr_set_canvas(GD_CANV(reg));
169    gr_set_fcolor(0x00);
170    gr_rect(RECT_EXPAND_ARGS(&nrect));
171 //   Spew(DSRC_UI_Gadget, ("after the 2d part of that...\n"));
172    return(0);
173 }
174 
175 uchar gad_mono_blank_expose(LGRegion *reg, LGRect *r)
176 {
177    LGRegion *dummy;
178    LGRect *dummy2;
179    dummy = reg; dummy2 = r;
180 
181    return (0);
182 }
183 */
184 
gad_Mac_blank_expose(LGRegion * reg,LGRect * r)185 uchar gad_Mac_blank_expose(LGRegion *reg, LGRect *r)
186 {
187 	LGRect nrect;
188 
189 	region_abs_rect(reg, r, &nrect);
190 	SCALE_RECT(&nrect, GD_GADG(reg)->conversion);
191 	gr_set_canvas((grs_canvas *)GD_CANV(reg));
192 	gr_set_fcolor(0x00);
193 	gr_rect(RECT_EXPAND_ARGS(&nrect));
194 	return(0);
195 }
196 
197 
draw_resource_bm(Ref id,int x,int y)198 errtype draw_resource_bm(Ref id, int x, int y)
199 {
200    FrameDesc *f;
201    int a1,a2,a3,a4;
202    short *ppall;
203 
204    STORE_CLIP(a1,a2,a3,a4);
205 //   Spew(DSRC_UI_Utilities, ("cliprect = (%d, %d)(%d, %d)\n",a1,a2,a3,a4));
206    // Spew(DSRC_UI_Utilities, ("drawing bitmap to (%d, %d)\n",x,y));
207    f = FrameLock(id);
208 
209    // Set the palette right
210    /*¥¥¥ Ignore for now
211    if (f->pallOff)
212    {
213       ppall = (short *) (((uchar *) RefGet(id)) + f->pallOff);
214       // Spew(DSRC_UI_Utilities, ("ppall = %d   *ppall + 1 = %d\n",*ppall, *(ppall + 1)));
215       gr_set_pal(*ppall,*(ppall + 1),(uchar *)(ppall + 2));
216    }
217    */
218    f->bm.bits = (uchar *)(f+1);
219    gr_bitmap(&f->bm, x, y);
220    RefUnlock(id);
221    return (OK);
222 }
223 
resource_bm_width(Ref id)224 int resource_bm_width(Ref id)
225 {
226    FrameDesc *f;
227    int n;
228 
229    f = FrameLock(id);
230    n = f->bm.w;
231    // Spew(DSRC_UI_Utilities, ("resource_bm_width = %d\n",n));
232    RefUnlock(id);
233    return (n);
234 }
235 
resource_bm_height(Ref id)236 int resource_bm_height(Ref id)
237 {
238    FrameDesc *f;
239    int n;
240 
241    f = FrameLock(id);
242    n = f->bm.h;
243    // Spew(DSRC_UI_Utilities, ("resource_bm_height = %d\n",n));
244    RefUnlock(id);
245    return (n);
246 }
247 
248 // Initialize the overall gadget system.  Should be called once, when the first gadget_init is
249 // triggered
gadget_initialize_system(void)250 errtype gadget_initialize_system(void)
251 {
252 #ifdef INIT_RESOURCES_HERE
253    ResInit();
254    ResAddPath(RESPATH);
255    for (i = 0; i < NUM_RESOURCE_FILES; i++)
256       ResOpenFile(resource_files[i]);
257 #endif
258    return(OK);
259 }
260 
261 // Initialize a gadget system for a particular display type.  Returns the gadget that is the "root" gadget
262 // for that display.
gadget_init(int display_type,LGPoint extent)263 Gadget *gadget_init(int display_type, LGPoint extent)
264 {
265    Gadget *retgad;
266    GadgetData *gd;
267    RectCallback fn;
268    LGRect r;
269 
270 //	if ((extent.x <= 0) || (extent.y <= 0))
271 //		Spew(DSRC_UI_Bounds, ("Nonpositive extent in gadget_init!\n"));
272    if (!gadget_initialization)
273    {
274       gadget_initialization = TRUE;
275       gadget_initialize_system();
276    }
277 
278    // Make a rectangle out of the extent
279    r.ul.x = 0;  r.ul.y = 0;
280    r.lr = extent;
281 
282    // Make the basic gadget
283    retgad = (Gadget *)malloc(sizeof(Gadget));
284    retgad->gclass = CLASS_ROOT;
285    retgad->tng_data = NULL;
286    retgad->draw_parts = TNG_ALLPARTS;
287    retgad->handler_id = -1;
288    retgad->destroy_func = NULL;
289    retgad->conversion.x = extent.x / BASELINE_X;
290    retgad->conversion.y = extent.y / BASELINE_Y;
291 
292    // Fill out the user data structure
293    gd = (GadgetData *)malloc(sizeof(GadgetData));
294    gd->g = retgad;
295    gd->name  = (char *)malloc(8 * sizeof(char));
296 //   lg_sprintf(gd->name, "root%d\0", display_type);
297    sprintf(gd->name, "root%d", display_type);
298 
299    // Set the right kind o' callback
300    switch (display_type)
301    {
302 /*    case DISPLAY_VGA:
303       case DISPLAY_SVGA:
304       case DISPLAY_MODEX:
305          fn = &gad_vga_blank_expose;
306          break;
307       case DISPLAY_MONO:
308          fn = &gad_mono_blank_expose;
309          break; */
310 	  case DISPLAY_MAC:
311 	  	 fn = &gad_Mac_blank_expose;
312 	  	 break;
313    }
314 
315    // Create that durned rep
316 
317    retgad->rep = (LGRegion *)malloc(sizeof(LGRegion));
318    region_create(NULL, retgad->rep, &r, 0, 0, REG_AUTOMATIC, NULL, NULL, NULL, gd);
319    retgad->rep->expose = fn;
320    retgad->rep->device_type = display_type;
321 
322    switch (display_type)
323    {
324 /*    case DISPLAY_VGA:
325          gad_vga_init(retgad, extent);
326          break;
327       case DISPLAY_MODEX:
328          gad_modex_init(retgad, extent);
329          break;
330       case DISPLAY_SVGA:
331          gad_svga_init(retgad, extent);
332          break;
333       case DISPLAY_MONO:
334          gad_mono_init(retgad, extent);
335          break; */
336 	  case DISPLAY_MAC:
337 	  	 gad_Mac_init(retgad, extent);
338 	  	 break;
339    }
340 
341    return(retgad);
342 }
343 
344 // Forces a gadget to display itself
gadget_display(Gadget * g,LGRect * r)345 errtype gadget_display(Gadget *g, LGRect *r)
346 {
347    return(gadget_display_part(g,r,TNG_ALLPARTS));
348 }
349 
gadget_display_part(Gadget * g,LGRect * r,ushort partmask)350 errtype gadget_display_part(Gadget *g, LGRect *r, ushort partmask)
351 {
352    g->draw_parts = partmask;
353    if (r == NULL)
354       region_expose(g->rep, g->rep->r);
355    else
356       region_expose(g->rep, r);
357    return(OK);
358 }
359 
gadget_shutdown()360 errtype gadget_shutdown()
361 {
362    gr_close();
363    return(OK);
364 }
365 
366 
367 // Destroys the gadget and any children gadgets
368 uchar in_destroy = FALSE;
gadget_destroy(Gadget ** pvic)369 errtype gadget_destroy(Gadget **pvic)
370 {
371    LGRegion *curp, *nextp;
372    Gadget *victim;
373    uchar inner_destroy;
374 
375    victim = *pvic;
376 
377    inner_destroy = in_destroy;
378    if (!inner_destroy)
379       in_destroy = TRUE;
380 /*
381    if (victim->rep != NULL)
382    {
383        Spew(DSRC_UI_Gadget, ("Destroying %s!\n",GD_NAME(victim->rep)));
384       if (victim->rep->user_data == NULL)
385          Warning(("Attempting to destroy gadget with no user_data!\n"));
386    }
387    else
388        Spew(DSRC_UI_Gadget, ("rep is NULL!\n"));
389 */
390    if (victim == NULL)
391    {
392       // Spew(DSRC_UI_Bounds, ("Attempted to destroy null gadget!\n"));
393       return(ERR_NULL);
394    }
395 
396    if (victim->rep != NULL)
397    {
398       curp = victim->rep->sub_region;
399       while (curp != NULL)
400       {
401          nextp = curp->next_region;
402 
403          // Is this thing a gadget, or a region hung off of us?
404          if (curp->user_data != NULL)
405             gadget_destroy(&(GD_GADG(curp)));
406          else
407             region_destroy(curp, FALSE);
408          curp = nextp;
409       }
410       region_destroy(victim->rep, !inner_destroy);
411    }
412 
413    if (victim->destroy_func != NULL)
414       victim->destroy_func(victim, NULL);
415    free(*pvic);
416    *pvic = NULL;
417 
418    if (!inner_destroy)
419    {
420       in_destroy = FALSE;
421    }
422    return (OK);
423 }
424 
425 // Moves the gadget to a new x, y, z coordinate (relative)
gadget_frob_canvas(LGRegion * reg,void * data)426 uchar gadget_frob_canvas(LGRegion *reg, void *data)
427 {
428    LGPoint delta;
429    Gadget *g;
430    // Spew(DSRC_UI_Gadget, ("Tippie-top of frob!\n"));
431    delta = *((LGPoint *)(data));
432    g = GD_GADG(reg);
433    // Spew(DSRC_UI_Gadget, ("Frobbing canvas on %s:  Delta = (%d,%d)\n",GD_NAME(g->rep),delta.x,delta.y));
434    gr_init_sub_canvas((grs_canvas *)g->parent->device_data, (grs_canvas *)g->device_data,
435       g->rep->r->ul.x + delta.x, g->rep->r->ul.y + delta.y,
436       RectWidth(g->rep->r), RectHeight(g->rep->r));
437    ((LGPoint *)(data))->x = 0;
438    ((LGPoint *)(data))->y = 0;
439    return(FALSE);
440 }
441 
gadget_move(Gadget * g,LGPoint coord,int z)442 errtype gadget_move(Gadget *g, LGPoint coord, int z)
443 {
444    LGPoint delta;
445 
446    if (g == NULL)
447    {
448       // Spew(DSRC_UI_Bounds, ("Attempted to move null gadget!\n"));
449       return(ERR_NULL);
450    }
451    if ((coord.x < 0) || (coord.y < 0))
452    {
453       // Spew(DSRC_UI_Bounds, ("Attempted to move gadget to negative point!\n"));
454       return(ERR_RANGE);
455    }
456    delta.x = coord.x - g->rep->r->ul.x;
457    delta.y = coord.y - g->rep->r->ul.y;
458 //   region_traverse(g->rep, &gadget_frob_canvas, BOTTOM_TO_TOP, &delta);
459    region_move(g->rep, coord.x, coord.y, z);
460    return (OK);
461 }
462 
gadget_resize(Gadget * g,int xsize,int ysize)463 errtype gadget_resize(Gadget* g, int xsize, int ysize)
464 {
465    if (g == NULL)
466    {
467       // Spew(DSRC_UI_Bounds, ("Attempted to resize null gadget!\n"));
468       return(ERR_NULL);
469    }
470    if ((xsize < 0) || (ysize < 0))
471    {
472       // Spew(DSRC_UI_Bounds, ("Attempted to give region negative size\n"));
473       return(ERR_RANGE);
474    }
475    region_resize(g->rep, xsize, ysize);
476    return (OK);
477 }
478 
479 
gad_callback_install(Gadget * g,ushort event_type,ushort condition,TNGCallback tngcb,intptr_t user_data,int * id)480 errtype gad_callback_install(Gadget *g, ushort event_type, ushort condition, TNGCallback tngcb, intptr_t user_data, int *id)
481 {
482    return(tng_install_callback(g->tng_data, event_type, condition, tngcb, user_data, id));
483 }
484 
gad_callback_uninstall(Gadget * g,int id)485 errtype gad_callback_uninstall(Gadget *g, int id)
486 {
487    return(tng_uninstall_callback(g->tng_data,id));
488 }
489 
490 /*
491 uchar gadget_tng_mono_expose(LGRegion *reg, LGRect *r)
492 {
493    LGRegion *dummy;
494    LGRect *dummy2;
495    dummy = reg;
496    dummy2 = r;
497 
498    return (FALSE);
499 }
500 
501 uchar gadget_tng_vga_expose(LGRegion *reg, LGRect *r)
502 {
503    ushort partmask;
504    LGRect nrect;
505    int c1,c2,c3,c4;
506    LGPoint loc;
507    Gadget *g;
508 
509    g = GD_GADG(reg);
510    partmask = g->draw_parts;
511    if (GD_CANV(reg) != NULL)
512    {
513       gr_set_canvas(GD_CANV(reg));
514       region_abs_rect(reg, r, &nrect);
515       // Spew(DSRC_UI_Gadget, ("About to draw gadget %s\n",GD_NAME(reg)));
516       // Spew(DSRC_UI_Gadget, ("r = (%d,%d)(%d,%d)\n",RECT_EXPAND_ARGS(r)));
517       // Spew(DSRC_UI_Gadget, ("nrect = (%d,%d)(%d,%d)\n",RECT_EXPAND_ARGS(&nrect)));
518       STORE_CLIP(c1,c2,c3,c4);
519       gr_set_cliprect(nrect.ul.x, nrect.ul.y, nrect.lr.x , nrect.lr.y);
520       loc.x = g->rep->abs_x;  loc.y = g->rep->abs_y;
521       // Spew(DSRC_UI_Gadget, ("abs_x = %d  abs_y = %d\n",loc.x, loc.y));
522       g->tng_data->draw_func(g->tng_data, partmask, loc);
523       RESTORE_CLIP(c1,c2,c3,c4);
524    }
525    else
526       // Spew(DSRC_UI_Gadget, ("Got a NULL canvas here, buddy...region %s\n",GD_NAME(reg)));
527    return(OK);
528 }
529 */
gadget_tng_Mac_expose(LGRegion * reg,LGRect * r)530 uchar gadget_tng_Mac_expose(LGRegion *reg, LGRect *r)
531 {
532 	ushort	partmask;
533 	LGRect	nrect;
534 	int 		c1,c2,c3,c4;
535 	LGPoint	loc;
536 	Gadget	*g;
537 
538 	g = GD_GADG(reg);
539 	partmask = g->draw_parts;
540 	if (GD_CANV(reg) != NULL)
541 	{
542 		gr_set_canvas((grs_canvas *)GD_CANV(reg));
543 		region_abs_rect(reg, r, &nrect);
544 		STORE_CLIP(c1,c2,c3,c4);
545 		gr_set_cliprect(nrect.ul.x, nrect.ul.y, nrect.lr.x , nrect.lr.y);
546 		loc.x = g->rep->abs_x;  loc.y = g->rep->abs_y;
547 		g->tng_data->draw_func(g->tng_data, partmask, loc);
548 		RESTORE_CLIP(c1,c2,c3,c4);
549 	}
550 	return(OK);
551 }
552 
gadget_tng_mouse_handler(uiEvent * e,LGRegion * r,intptr_t state)553 uchar gadget_tng_mouse_handler(uiEvent *e, LGRegion *r, intptr_t state)
554 {
555    Gadget *g;
556    uiMouseEvent *mickey;
557    LGPoint rel;
558    intptr_t dummy;
559    dummy = state;
560 
561    mickey = (uiMouseEvent *)e;
562    g = GD_GADG(r);
563    rel.x = mickey->pos.x - r->abs_x;
564    rel.y = mickey->pos.y - r->abs_y;
565    return(g->tng_data->mousebutt(g->tng_data, mickey->action, rel));
566 }
567 
gadget_tng_mouse_move_handler(uiEvent * e,LGRegion * r,intptr_t state)568 uchar gadget_tng_mouse_move_handler(uiEvent *e, LGRegion *r, intptr_t state)
569 {
570    Gadget *g;
571    uiMouseEvent *mickey;
572    LGPoint rel;
573    intptr_t dummy;
574    dummy = state;
575 
576    mickey = (uiMouseEvent *)e;
577    g = GD_GADG(r);
578    rel.x = mickey->pos.x - r->abs_x;
579    rel.y = mickey->pos.y - r->abs_y;
580    return(g->tng_data->mousemove(g->tng_data, rel));
581 }
582 
gadget_tng_keyboard_handler(uiEvent * e,LGRegion * r,intptr_t state)583 uchar gadget_tng_keyboard_handler(uiEvent *e, LGRegion *r, intptr_t state)
584 {
585    Gadget *g;
586    uiCookedKeyEvent *cke;
587    intptr_t dummy;
588    dummy = state;
589 
590    if ((e->type != UI_EVENT_KBD_COOKED) || !(e->subtype & KB_FLAG_DOWN))
591       return FALSE;
592    cke = (uiCookedKeyEvent *)e;
593    g = GD_GADG(r);
594    return(g->tng_data->keycooked(g->tng_data, cke->code));
595 }
596 
gadget_create_setup(Gadget ** pg,Gadget * parent,GadgetClass cl,LGRect * dim,int z,char * name)597 errtype gadget_create_setup(Gadget **pg, Gadget *parent, GadgetClass cl, LGRect *dim, int z, char *name)
598 {
599    Gadget *retgad;
600    GadgetData *gd;
601    TNG *pb_tng;
602    RectCallback fn;
603 
604    if ((RectWidth(dim) < 1) || (RectHeight(dim) < 1))
605    {
606       // Spew(DSRC_UI_Bounds, ("Nonpositive dimension of created gadget!\n"));
607       return 0;
608    }
609 
610    // Do those yummy mallocs
611    retgad = (Gadget *)malloc(sizeof(Gadget));
612    gd = (GadgetData *)malloc(sizeof(GadgetData));
613    pb_tng = (TNG *)malloc(sizeof(TNG));
614 
615    switch (parent->rep->device_type)
616    {
617 /*  case DISPLAY_VGA:
618       case DISPLAY_SVGA:
619       case DISPLAY_MODEX:
620          fn = &gadget_tng_vga_expose;
621          break;
622       case DISPLAY_MONO:
623          fn = &gadget_tng_mono_expose;
624          break; */
625       case DISPLAY_MAC:
626          fn = &gadget_tng_Mac_expose;
627          break;
628    }
629 
630    // Fill out basic gadgety info
631    retgad->tng_data = pb_tng;
632    retgad->draw_parts = TNG_ALLPARTS;
633    retgad->gclass = cl;
634    retgad->parent = parent;
635 //   retgad->device_data = gr_alloc_sub_canvas(parent->device_data, dim->ul.x, dim->ul.y, RectWidth(dim), RectHeight(dim));
636    retgad->device_data = parent->device_data;
637    retgad->conversion = parent->conversion;
638    retgad->handler_id = -1;
639    retgad->destroy_func = NULL;
640 
641    // Fill in the gadget data info
642    gd->name = (char *)malloc((strlen(name) + 1) * sizeof(char));
643    strcpy(gd->name, name);
644    gd->g = retgad;
645 
646    // Create that durned rep
647    retgad->rep = (LGRegion *)malloc(sizeof(LGRegion));
648    region_create(parent->rep, retgad->rep, dim, z, 0,
649       REG_USER_CONTROLLED | AUTOMANAGE_FLAG | STENCIL_CLIPPING | OBSCURATION_CHECK,
650       fn, NULL, NULL, gd);
651 
652    // Install the general pushbutton handler
653    uiInstallRegionHandler(retgad->rep, UI_EVENT_MOUSE_MOVE, &gadget_tng_mouse_move_handler, (intptr_t) retgad, &(retgad->handler_id));
654    uiInstallRegionHandler(retgad->rep, UI_EVENT_MOUSE, &gadget_tng_mouse_handler, (intptr_t) retgad, &(retgad->handler_id));
655    uiInstallRegionHandler(retgad->rep, UI_EVENT_KBD_COOKED, &gadget_tng_keyboard_handler, (intptr_t) retgad, &(retgad->handler_id));
656 
657    *pg = retgad;
658    return(OK);
659 }
660 
gadget_change_flags(Gadget * g,ulong flags,uchar on,uchar children)661 errtype gadget_change_flags(Gadget *g, ulong flags, uchar on, uchar children)
662 {
663    LGRegion *cur_child;
664    if (on)
665       g->rep->status_flags |= flags;
666    else
667       g->rep->status_flags &= ~flags;
668    if (children)
669    {
670       cur_child = g->rep->sub_region;
671       while (cur_child != NULL)
672       {
673          gadget_change_flags(GD_GADG(cur_child), flags, on, children);
674          cur_child = cur_child->next_region;
675       }
676    }
677    return(OK);
678 }
679