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 #include "tng.h"
21 #include "tngapp.h"
22 #include "rect.h"
23 #include "2d.h"
24 //#include <_ui.h>
25 
26 //	TNGDrawBase() draws base graphics for a TNG gadget.  All
27 //	TNG gadgets should call this function to draw their base as
28 //	the first thing in their draw function, unless the
29 //	TNG gadget's graphics fully and non-transparently occupy the
30 //	gadget area.  Partial-draw routines may skip this call
31 //	if they are drawing areas which don't need the gadget backdrop.
32 
33 LGPoint tngZeroPt = {0,0};		// everybody needs a zero point sometime
34 
35 TNGStyle stdTNGStyle = {
36    0x25C, 0, {6,6}, 0xff,
37    0x01, 0x1d, 0,
38    0x20,0x28,0x28,0x20};
39 
TNGInit(TNG * ptng,TNGStyle * sty,void * ui_data)40 errtype TNGInit(TNG *ptng, TNGStyle *sty, void *ui_data)
41 {
42    if (sty != NULL)
43       ptng->style = sty;
44    else
45       ptng->style = &stdTNGStyle;
46    ptng->ui_data = ui_data;
47    ptng->pcb = NULL;
48    ptng->draw_func = &tng_cb_draw;
49    ptng->mousebutt = &tng_cb_mousebutt;
50    ptng->mousemove = &tng_cb_mousemove;
51    ptng->keycooked = &tng_cb_keycooked;
52    ptng->keyscan   = &tng_cb_keyscan;
53    ptng->signal    = &tng_cb_signal;
54    ptng->flags     = 0;
55    return(OK);
56 }
57 
TNGDrawBase(TNG * ptng,LGPoint coord,LGPoint size)58 void TNGDrawBase(TNG *ptng, LGPoint coord, LGPoint size)
59 {
60 	short width,height;
61 	TNGStyle *pstyle;
62 	LGRect rect;
63    ushort flags;
64 	int i;
65 
66 //	If bitmap background, draw it
67 //	Else if tiled background, draw it
68 //	Else if background color, draw it
69 //	Else if gadget has transparencies, draw dialog underneath
70 
71 	pstyle = ptng->style;
72    flags = ptng->flags;
73    width = size.x;
74    height = size.y;
75 	if (flags & TNG_BMAPBACK)
76 		TNGDrawBitmapRef(pstyle->bitmapRef, coord);
77 	else if (flags & TNG_TILEBACK)
78 		TNGDrawTileMapRef(pstyle->bitmapRef, coord);
79 	else if (pstyle->backColor)
80    {
81       gr_set_fcolor(pstyle->backColor);
82       gr_rect(coord.x, coord.y, coord.x + width, coord.y + height);
83    }
84 
85 //	If bevel border, draw it
86 
87 	if ((flags & TNG_NOBORDER) == 0)
88 		{
89 		if (flags & TNG_BEVEL)
90 			{
91 
92 			gr_cset_fcolor(grd_canvas,
93 				pstyle->bordColor[(flags & TNG_BEVELMASK) >> TNG_BEVELSHIFT]);
94          gr_hline(coord.x, coord.y, coord.x + width - 1);
95          gr_vline(coord.x, coord.y, coord.y + height - 1);
96 
97 			gr_cset_fcolor(grd_canvas,
98 				pstyle->bordColor[((flags ^ TNG_INVERTBEVEL) &
99 					TNG_BEVELMASK) >> TNG_BEVELSHIFT]);
100          gr_hline(coord.x, coord.y + height - 1, coord.x + width - 1);
101          gr_vline(coord.x + width - 1, coord.y, coord.y + height - 1);
102 			}
103 
104 //	Else if fat border, draw it
105 
106 		else if (flags & TNG_FATBORDER)
107 			{
108 //			rect = *(TNG_AREARECT(ptng));
109 //         rect.ul = tngZeroPt;
110          rect.ul = coord;
111          rect.lr.x = rect.ul.x + width;
112          rect.lr.y = rect.lr.x + height;
113 			for (i = 0; i < 4; i++)
114 				{
115 				gr_cset_fcolor(grd_canvas, pstyle->bordColor[i]);
116             gr_box(rect.ul.x, rect.ul.y, rect.lr.x, rect.lr.y);
117 				rect.ul.x++;
118 				rect.ul.y++;
119 				rect.lr.x--;
120 				rect.lr.y--;
121 				}
122 			}
123 		}
124 }
125 
126 
127 //	TNGDrawBitmapRef() draws a bitmap of any kind, given ref.
128 //
129 //		ref = reference to bitmap (high word is res, low word is frame #)
130 //		pt  = point in current canvas at which to place u.l. of bitmap
131 
TNGDrawBitmapRef(Ref ref,LGPoint pt)132 void TNGDrawBitmapRef(Ref ref, LGPoint pt)
133 {
134 	FrameDesc *pfd;
135 	LGRect bitRect;
136 	LGRect cvRect;
137 
138 	pfd = FrameLock(ref);
139 	pfd->bm.bits = (uchar *) (pfd + 1);
140 
141 	bitRect.ul = pt;
142 	bitRect.lr.x = bitRect.ul.x + pfd->bm.w;
143 	bitRect.lr.y = bitRect.ul.y + pfd->bm.h;
144 	cvRect.ul.x = grd_clip.left;
145 	cvRect.ul.y = grd_clip.top;
146 	cvRect.lr.x = grd_clip.right + 1;
147 	cvRect.lr.y = grd_clip.bot + 1;
148    gr_bitmap(&pfd->bm, pt.x, pt.y);
149 
150 	RefUnlock(REFID(ref));
151 }
152 
153 //	-----------------------------------------------------------
154 //
155 //	TNGDrawTileMapRef() draws a bitmap repeated in the clip area.
156 //
157 //		ref = reference to bitmap (high word is res, low word is frame #)
158 //		pt  = point at which to render first bitmap; this routine tiles
159 //				from this point to l.r. of cliprect.
160 
TNGDrawTileMapRef(Ref ref,LGPoint pt)161 void TNGDrawTileMapRef(Ref ref, LGPoint pt)
162 {
163 	FrameDesc *pfd;
164 	short startx;
165 
166 	pfd = FrameLock(ref);
167 	pfd->bm.bits = (uchar *) (pfd + 1);
168 
169 	while ((pt.y + pfd->bm.h) < grd_clip.top)
170 		pt.y += pfd->bm.h;
171 	while ((pt.x + pfd->bm.w) < grd_clip.left)
172 		pt.x += pfd->bm.w;
173 
174 	while (pt.y < grd_clip.bot)
175 		{
176 		startx = pt.x;
177 		while (pt.x < grd_clip.right)
178 			{
179          gr_bitmap(&pfd->bm, pt.x, pt.y);
180 			pt.x += pfd->bm.w;
181 			}
182 		pt.x = startx;
183 		pt.y += pfd->bm.h;
184 		}
185 
186 	RefUnlock(REFID(ref));
187 }
188 
TNGDrawText(Id id,char * text,int x,int y)189 errtype TNGDrawText(Id id, char *text, int x, int y)
190 {
191    gr_set_font(FontLock(id));
192    gr_string(text, x, y);
193    ResUnlock(id);
194    return(OK);
195 }
196 
197 // --------------------------------------------
198 // Callback Functions
199 // --------------------------------------------
200 
tng_install_callback(TNG * ptng,ushort event_type,ushort cond,TNGCallback cbfn,intptr_t user_data,int * pid)201 errtype tng_install_callback(TNG *ptng, ushort event_type, ushort cond, TNGCallback cbfn, intptr_t user_data, int *pid)
202 {
203    TNG_CB *tngcb, *curp, *oldp;
204    int oldid = 0;
205 
206    if (ptng == NULL)
207    {
208 //      Spew(DSRC_UI_Bounds, ("Attempted to install callback on NULL TNG!\n"));
209       return(ERR_NULL);
210    }
211 
212    tngcb = (TNG_CB *)malloc(sizeof(TNG_CB));
213    tngcb->condition = cond;
214    tngcb->user_data = user_data;
215    tngcb->cb = cbfn;
216    tngcb->event_type = event_type;
217    tngcb->next_cb = NULL;
218 
219    curp = ptng->pcb;
220    oldp = NULL;
221    while (curp != NULL)
222    {
223       oldp = curp;
224       curp = curp->next_cb;
225    }
226    if (oldp == NULL)
227       ptng->pcb = tngcb;
228    else
229    {
230       oldp->next_cb = tngcb;
231       oldid = oldp->id + 1;
232    }
233    tngcb->id = oldid;
234    *pid = oldid;
235    return (OK);
236 }
237 
tng_uninstall_callback(TNG * ptng,int id)238 errtype tng_uninstall_callback(TNG *ptng, int id)
239 {
240    TNG_CB *curp, *oldp;
241 
242    if (ptng == NULL)
243    {
244 //      Spew(DSRC_UI_Bounds, ("Attempted to remove callback from null TNG!\n"));
245       return(ERR_NULL);
246    }
247 
248    curp = ptng->pcb;
249    oldp = NULL;
250    while (curp->id != id)
251    {
252       oldp = curp;
253       curp = curp->next_cb;
254       if (curp == NULL)
255          return(ERR_RANGE);
256    }
257    if (oldp == NULL)
258    {
259       ptng->pcb = curp->next_cb;
260    }
261    else
262    {
263       oldp->next_cb = curp->next_cb;
264    }
265    free(curp);
266    return(OK);
267 }
268 
tng_cb_mousebutt(TNG * ptng,uchar type,LGPoint loc)269 uchar tng_cb_mousebutt(TNG *ptng, uchar type, LGPoint loc)
270 {
271    TNG_CB *tngcb;
272    uchar retval = FALSE;
273    uchar newret;
274 
275    tngcb = ptng->pcb;
276    while (tngcb != NULL)
277    {
278 //      Spew(DSRC_TNG_Callback, ("In while part of tng_cb_mousebutt...\n"));
279       if (tngcb->event_type == TNG_EVENT_MOUSE)
280       {
281          newret = FALSE;
282          if (type & tngcb->condition)
283          {
284             ptng->cb_data = (intptr_t)&loc;
285             newret = tngcb->cb(ptng->ui_data, tngcb->user_data);
286          }
287          if (newret)
288             retval = newret;
289       }
290       tngcb = tngcb->next_cb;
291    }
292    return(retval);
293 }
294 
tng_cb_keycooked(TNG * ptng,ushort key)295 uchar tng_cb_keycooked(TNG *ptng, ushort key)
296 {
297    TNG_CB *tngcb;
298    uchar retval = FALSE;
299    uchar newret;
300 
301    tngcb = ptng->pcb;
302    while (tngcb != NULL)
303    {
304       if (tngcb->event_type == TNG_EVENT_KBD_COOKED)
305       {
306          newret = FALSE;
307          if (key == tngcb->condition)
308          {
309             ptng->cb_data = key;
310             newret = tngcb->cb(ptng->ui_data, tngcb->user_data);
311          }
312          if (newret)
313             retval = newret;
314       }
315       tngcb = tngcb->next_cb;
316    }
317    return(retval);
318 }
319 
tng_cb_signal(TNG * ptng,ushort signal)320 uchar tng_cb_signal(TNG *ptng, ushort signal)
321 {
322    TNG_CB *tngcb;
323    uchar retval = FALSE;
324    uchar newret;
325 
326    tngcb = ptng->pcb;
327    while (tngcb != NULL)
328    {
329       if (tngcb->event_type == TNG_EVENT_SIGNAL)
330       {
331          newret = FALSE;
332          if (signal & tngcb->condition)
333          {
334             ptng->cb_data = signal;
335             newret = tngcb->cb(ptng->ui_data, tngcb->user_data);
336          }
337          if (newret)
338             retval = newret;
339       }
340       tngcb = tngcb->next_cb;
341    }
342    return(retval);
343 }
344 
tng_cb_keyscan(TNG * ptng,ushort scan)345 uchar tng_cb_keyscan(TNG *ptng, ushort scan)
346 {
347    TNG_CB *tngcb;
348    uchar retval = FALSE;
349    uchar newret;
350 
351    tngcb = ptng->pcb;
352    while (tngcb != NULL)
353    {
354       if (tngcb->event_type == TNG_EVENT_KBD_RAW)
355       {
356          newret = FALSE;
357          if (scan == tngcb->condition)
358          {
359             ptng->cb_data = scan;
360             newret = tngcb->cb(ptng->ui_data, tngcb->user_data);
361          }
362          if (newret)
363             retval = newret;
364       }
365       tngcb = tngcb->next_cb;
366    }
367    return(retval);
368 }
369 
tng_cb_mousemove(TNG * ptng,LGPoint loc)370 uchar tng_cb_mousemove(TNG *ptng, LGPoint loc)
371 {
372    TNG_CB *tngcb;
373    uchar retval = FALSE;
374    uchar newret;
375    LGPoint dummy;
376    dummy = loc;
377 
378    tngcb = ptng->pcb;
379    while (tngcb != NULL)
380    {
381       if (tngcb->event_type == TNG_EVENT_MOUSE_MOVE)
382       {
383           ptng->cb_data = (intptr_t)&loc;
384          newret = tngcb->cb(ptng->ui_data, tngcb->user_data);
385          if (newret)
386             retval = newret;
387       }
388       tngcb = tngcb->next_cb;
389    }
390    return(retval);
391 }
392 
tng_cb_draw(TNG * ptng,ushort partmask,LGPoint loc)393 errtype tng_cb_draw(TNG *ptng, ushort partmask, LGPoint loc)
394 {
395 #ifndef NO_DUMMIES
396    LGPoint dummy; ushort dummy2; dummy2 = partmask; dummy = loc;
397 #endif
398    ptng->signal(ptng, TNG_SIGNAL_EXPOSE);
399    return(OK);
400 }
401 
tng_absloc(TNG * ptng)402 LGPoint tng_absloc(TNG* ptng)
403 {
404    LGRegion* r= ((Gadget*)(ptng->ui_data))->rep;
405    LGPoint pt;
406    pt.x = r->abs_x;
407    pt.y = r->abs_y;
408    return pt;
409 }
410