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