maug
Quick and dirty C mini-augmentation library.
retrowin.h
Go to the documentation of this file.
1
2#ifndef RETROW3D_H
3#define RETROW3D_H
4
49#ifndef RETROWIN_TRACE_LVL
50# define RETROWIN_TRACE_LVL 0
51#endif /* !RETROWIN_TRACE_LVL */
52
58#define RETROWIN_FLAG_INIT_GUI 0x10
59
60#define RETROWIN_FLAG_INIT_BMP 0x20
61
62#define RETROWIN_FLAG_GUI_LOCKED 0x04
63
64#define RETROWIN_FLAG_BORDER_NONE 0x00
65#define RETROWIN_FLAG_BORDER_GRAY 0x01
66#define RETROWIN_FLAG_BORDER_BLUE 0x02
67
68#define retrowin_win_is_active( win ) \
69 (RETROWIN_FLAG_INIT_BMP == (RETROWIN_FLAG_INIT_BMP & (win)->flags))
70
71#define RETROWIN_FLAG_BORDER_MASK 0x03
72
73#define retrowin_lock_gui( win ) \
74 if( \
75 RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & (win)->flags) && \
76 RETROWIN_FLAG_GUI_LOCKED != (RETROWIN_FLAG_GUI_LOCKED & (win)->flags) \
77 ) { \
78 /* debug_printf( RETROWIN_TRACE_LVL, "locking managed gui handle %p...", \
79 (win)->gui_h ); */ \
80 maug_mlock( (win)->gui_h, (win)->gui_p ); \
81 maug_cleanup_if_null_lock( struct RETROGUI*, (win)->gui_p ); \
82 (win)->flags |= RETROWIN_FLAG_GUI_LOCKED; \
83 /* debug_printf( RETROWIN_TRACE_LVL, "locked managed gui to pointer %p!", \
84 (win)->gui_p ); */ \
85 }
86
87#define retrowin_unlock_gui( win ) \
88 if( \
89 RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & (win)->flags) && \
90 RETROWIN_FLAG_GUI_LOCKED == (RETROWIN_FLAG_GUI_LOCKED & (win)->flags) \
91 ) { \
92 /* debug_printf( RETROWIN_TRACE_LVL, "unlocking managed gui pointer %p...", \
93 (win)->gui_h ); */ \
94 maug_munlock( (win)->gui_h, (win)->gui_p ); \
95 (win)->flags &= ~RETROWIN_FLAG_GUI_LOCKED; \
96 }
97
98#define retrowin_gui_is_locked( win ) \
99 (RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & (win)->flags) && \
100 RETROWIN_FLAG_GUI_LOCKED == (RETROWIN_FLAG_GUI_LOCKED & (win)->flags))
101
102struct RETROWIN {
103 uint8_t flags;
104 retrogui_idc_t idc;
107 MAUG_MHANDLE gui_h;
108 struct RETROGUI* gui_p;
109#ifndef RETROWIN_NO_BITMAP
110 retroflat_blit_t gui_bmp;
111#endif /* !RETROWIN_NO_BITMAP */
112};
113
114MERROR_RETVAL retrowin_redraw_win_stack( struct MDATA_VECTOR* win_stack );
115
120
136 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc_active,
137 RETROFLAT_IN_KEY* p_input, struct RETROFLAT_INPUT* input_evt );
138
144 struct MDATA_VECTOR* win_stack,
145 retrogui_idc_t idc_win, retrogui_idc_t idc_ctl );
146
147void retrowin_free_win( struct RETROWIN* win );
148
149MERROR_RETVAL retrowin_free_all_win( struct MDATA_VECTOR* win_stack );
150
151ssize_t retrowin_get_by_idc(
152 retrogui_idc_t idc, struct MDATA_VECTOR* win_stack );
153
162ssize_t retrowin_push_win(
163 struct RETROGUI* gui, struct MDATA_VECTOR* win_stack,
164 retrogui_idc_t idc, const maug_path font_filename,
166 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
167
174 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc );
175
176#ifdef RETROW3D_C
177
178static MERROR_RETVAL _retrowin_draw_border( struct RETROWIN* win ) {
179 MERROR_RETVAL retval = MERROR_OK;
180 uint8_t autolock_gui = 0;
181
182#if RETROWIN_TRACE_LVL > 0
183 debug_printf( RETROWIN_TRACE_LVL, "drawing window border..." );
184#endif /* RETROWIN_TRACE_LVL */
185
186 if( !retrowin_gui_is_locked( win ) ) {
187 retrowin_lock_gui( win );
188 autolock_gui = 1;
189 }
190
191 switch( RETROWIN_FLAG_BORDER_MASK & win->flags ) {
192 case RETROWIN_FLAG_BORDER_NONE:
193 retroflat_2d_rect(
194 win->gui_p->draw_bmp, RETROFLAT_COLOR_BLACK,
195 win->gui_p->x,
196 win->gui_p->y,
197 win->gui_p->w,
198 win->gui_p->h,
200 break;
201
202 case RETROWIN_FLAG_BORDER_GRAY:
203 retroflat_2d_rect(
204 win->gui_p->draw_bmp,
205 2 < retroflat_screen_colors() ?
206 RETROFLAT_COLOR_GRAY : RETROFLAT_COLOR_WHITE,
207 win->gui_p->x,
208 win->gui_p->y,
209 win->gui_p->w,
210 win->gui_p->h,
212
213 /* Draw the border. */
214 retroflat_2d_rect(
215 win->gui_p->draw_bmp,
216 2 < retroflat_screen_colors() ?
217 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK,
218 win->gui_p->x,
219 win->gui_p->y,
220 win->gui_p->w,
221 win->gui_p->h,
222 0 );
223 if( 2 < retroflat_screen_colors() ) {
224 /* Draw highlight lines only visible in >2-color mode. */
225 retroflat_2d_line(
226 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE,
227 win->gui_p->x + 1,
228 win->gui_p->y + 1,
229 win->gui_p->x + win->gui_p->w - 2,
230 win->gui_p-> y + 1, 0 );
231 retroflat_2d_line(
232 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE,
233 win->gui_p->x + 1,
234 win->gui_p->y + 2,
235 win->gui_p->x + 1,
236 win->gui_p->y + win->gui_p->h - 3, 0 );
237 }
238 break;
239
240 case RETROWIN_FLAG_BORDER_BLUE:
241 retroflat_2d_rect(
242 win->gui_p->draw_bmp,
243 2 < retroflat_screen_colors() ?
244 RETROFLAT_COLOR_BLUE : RETROFLAT_COLOR_BLACK,
245 win->gui_p->x,
246 win->gui_p->y,
247 win->gui_p->w,
248 win->gui_p->h,
250
251 /* Draw the border. */
252 retroflat_2d_rect(
253 win->gui_p->draw_bmp,
254 2 < retroflat_screen_colors() ?
255 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK,
256 win->gui_p->x + 2,
257 win->gui_p->y + 2,
258 win->gui_p->w - 4,
259 win->gui_p->h - 4,
260 0 );
261 retroflat_2d_rect(
262 win->gui_p->draw_bmp, RETROFLAT_COLOR_WHITE,
263 win->gui_p->x + 1,
264 win->gui_p->y + 1,
265 win->gui_p->w - 2,
266 win->gui_p->h - 2,
267 0 );
268 retroflat_2d_rect(
269 win->gui_p->draw_bmp,
270 2 < retroflat_screen_colors() ?
271 RETROGUI_COLOR_BORDER : RETROFLAT_COLOR_BLACK,
272 win->gui_p->x,
273 win->gui_p->y,
274 win->gui_p->w,
275 win->gui_p->h,
276 0 );
277 break;
278 }
279
280#if RETROWIN_TRACE_LVL > 0
281 debug_printf( RETROWIN_TRACE_LVL, "drawing window border complete!" );
282#endif /* RETROWIN_TRACE_LVL */
283
284cleanup:
285
286 if( autolock_gui ) {
287 retrowin_unlock_gui( win );
288 }
289
290 return retval;
291}
292
293/* === */
294
295static MERROR_RETVAL _retrowin_redraw_win( struct RETROWIN* win ) {
296 MERROR_RETVAL retval = MERROR_OK;
297 uint8_t autolock_gui = 0;
298
299 if( !retrowin_gui_is_locked( win ) ) {
300 retrowin_lock_gui( win );
301 autolock_gui = 1;
302 }
303
304 /* Dirty detection is in retrogui_redraw_ctls(). */
305
306#ifdef RETROWIN_NO_BITMAP
307 win->gui_p->draw_bmp = NULL;
308#else
309 retroflat_2d_lock_bitmap( &(win->gui_bmp) );
310 win->gui_p->draw_bmp = &(win->gui_bmp);
311#endif /* RETROWIN_NO_BITMAP */
312
313#if RETROWIN_TRACE_LVL > 0
314 debug_printf( RETROWIN_TRACE_LVL,
315 "redrawing window IDC " RETROGUI_IDC_FMT " at "
316 PXXY_FMT ", " PXXY_FMT "...",
317 win->idc, win->gui_p->x, win->gui_p->y );
318#endif /* RETROWIN_TRACE_LVL */
319
320#ifndef RETROWIN_NO_BITMAP
321 /* This is a bit of a hack... Set X/Y to 0 so that we draw at the top
322 * of the bitmap that will be used as a texture. Reset it below so input
323 * detection works!
324 */
325 win->gui_p->x = 0;
326 win->gui_p->y = 0;
327#endif /* !RETROWIN_NO_BITMAP */
328 retval = _retrowin_draw_border( win );
329 if( MERROR_OK == retval ) {
330 retval = retrogui_redraw_ctls( win->gui_p );
331 }
332#ifndef RETROWIN_NO_BITMAP
333 win->gui_p->x = win->x;
334 win->gui_p->y = win->y;
335
336 retroflat_2d_release_bitmap( &(win->gui_bmp) );
337#endif /* !RETROWIN_NO_BITMAP */
338
339 maug_cleanup_if_not_ok();
340
341#if RETROWIN_TRACE_LVL > 0
342 debug_printf( RETROWIN_TRACE_LVL,
343 "redraw of window IDC " RETROGUI_IDC_FMT " at "
344 PXXY_FMT ", " PXXY_FMT " complete!",
345 win->idc, win->gui_p->x, win->gui_p->y );
346#endif /* RETROWIN_TRACE_LVL */
347
348cleanup:
349
350 if( autolock_gui ) {
351 retrowin_unlock_gui( win );
352 }
353
354 return retval;
355}
356
357/* === */
358
359MERROR_RETVAL retrowin_redraw_win_stack( struct MDATA_VECTOR* win_stack ) {
360 MERROR_RETVAL retval = MERROR_OK;
361 size_t i = 0;
362 struct RETROWIN* win = NULL;
363 uint8_t autolock_stack = 0;
364
365 if( 0 == mdata_vector_ct( win_stack ) ) {
366 goto cleanup;
367 }
368
369 if( !mdata_vector_is_locked( win_stack ) ) {
370 mdata_vector_lock( win_stack );
371 autolock_stack = 1;
372 }
373
374 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
375 win = mdata_vector_get( win_stack, i, struct RETROWIN );
376 assert( NULL != win );
377
378 if( !retrowin_win_is_active( win ) ) {
379 continue;
380 }
381
382 retrowin_lock_gui( win );
383
384#ifndef RETROWIN_NO_BITMAP
385 if( RETROGUI_FLAGS_DIRTY == (RETROGUI_FLAGS_DIRTY & win->gui_p->flags) ) {
386#endif /* !RETROWIN_NO_BITMAP */
387#if RETROWIN_TRACE_LVL > 0
388 debug_printf( RETROWIN_TRACE_LVL,
389 "redrawing window idx " SIZE_T_FMT " with IDC " RETROGUI_IDC_FMT,
390 i, win->idc );
391#endif /* RETROWIN_TRACE_LVL */
392
393 /* Redraw the window bitmap, including controls. */
394 retval = _retrowin_redraw_win( win );
395 maug_cleanup_if_not_ok();
396#ifndef RETROWIN_NO_BITMAP
397 }
398#endif /* !RETROWIN_NO_BITMAP */
399
400#ifndef RETROWIN_NO_BITMAP
401 /* Always blit the finished window to the screen, to compensate for e.g.
402 * the implicit screen-clearing of the engine loop.
403 */
404 retval = retroflat_2d_blit_win(
405 &(win->gui_bmp), win->gui_p->x, win->gui_p->y );
406#endif /* !RETROWIN_NO_BITMAP */
407
408 retrowin_unlock_gui( win );
409
410#if RETROWIN_TRACE_LVL > 0
411 debug_printf( RETROWIN_TRACE_LVL,
412 "redraw of window idx " SIZE_T_FMT " with IDC " RETROGUI_IDC_FMT
413 " complete!",
414 i, win->idc );
415#endif /* RETROWIN_TRACE_LVL */
416 }
417
418#if RETROWIN_TRACE_LVL > 0
419 debug_printf( RETROWIN_TRACE_LVL, "redraw of all windows complete!" );
420#endif /* RETROWIN_TRACE_LVL */
421
422cleanup:
423
424 if( autolock_stack ) {
425 mdata_vector_unlock( win_stack );
426 }
427
428 return retval;
429}
430
431/* === */
432
434 MERROR_RETVAL retval = MERROR_OK;
435 size_t i = 0;
436 struct RETROWIN* win = NULL;
437 uint8_t autolock_stack = 0;
438
439 if( 0 == mdata_vector_ct( win_stack ) ) {
440 goto cleanup;
441 }
442
443 if( !mdata_vector_is_locked( win_stack ) ) {
444 mdata_vector_lock( win_stack );
445 autolock_stack = 1;
446 }
447
448 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
449 win = mdata_vector_get( win_stack, i, struct RETROWIN );
450 assert( NULL != win );
451
452 if( !retrowin_win_is_active( win ) ) {
453 continue;
454 }
455
456 retrowin_lock_gui( win );
457
458#if RETROWIN_TRACE_LVL > 0
459 debug_printf( RETROWIN_TRACE_LVL,
460 "refreshing window idx " SIZE_T_FMT " with IDC " RETROGUI_IDC_FMT,
461 i, win->idc );
462#endif /* RETROWIN_TRACE_LVL */
463
464 win->gui_p->flags |= RETROGUI_FLAGS_DIRTY;
465
466 retrowin_unlock_gui( win );
467 }
468
469cleanup:
470
471 if( autolock_stack ) {
472 mdata_vector_unlock( win_stack );
473 }
474
475 return retval;
476}
477
478/* === */
479
481 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc_active,
482 RETROFLAT_IN_KEY* p_input, struct RETROFLAT_INPUT* input_evt
483) {
484 retrogui_idc_t idc_out = RETROGUI_IDC_NONE;
485 MERROR_RETVAL retval = MERROR_OK;
486 struct RETROWIN* win = NULL;
487 int autolock = 0;
488 ssize_t win_idx = -1;
489
490 if( !mdata_vector_is_locked( win_stack ) ) {
491 mdata_vector_lock( win_stack );
492 autolock = 1;
493 }
494
495 win_idx = retrowin_get_by_idc( idc_active, win_stack );
496 if( 0 > win_idx ) {
497 /* No window found! */
498 error_printf( "polling missing window!" );
499 goto cleanup;
500 }
501
502 win = mdata_vector_get( win_stack, win_idx, struct RETROWIN );
503 assert( NULL != win );
504 assert( idc_active == win->idc );
505 if( !retrowin_win_is_active( win ) ) {
506 /* Window not initialized! */
507 error_printf( "polling uninitialized window!" );
508 goto cleanup;
509 }
510
511 retrowin_lock_gui( win );
512 if( 0 != *p_input ) {
513#if RETROWIN_TRACE_LVL > 0
514 debug_printf( RETROWIN_TRACE_LVL,
515 "polling window idx " SIZE_T_FMT " with IDC " RETROGUI_IDC_FMT,
516 win_idx, win->idc );
517#endif /* RETROWIN_TRACE_LVL */
518 }
519 idc_out = retrogui_poll_ctls( win->gui_p, p_input, input_evt );
520 retrowin_unlock_gui( win );
521
522cleanup:
523
524 if( MERROR_OK != retval ) {
525 error_printf( "error polling windows!" );
526 idc_out = RETROGUI_IDC_NONE;
527 }
528
529 if( autolock ) {
530 mdata_vector_unlock( win_stack );
531 }
532
533 return idc_out;
534}
535
536/* === */
537
539 struct MDATA_VECTOR* win_stack,
540 retrogui_idc_t idc_win, retrogui_idc_t idc_ctl
541) {
542 ssize_t idx_out = -1;
543 MERROR_RETVAL retval = MERROR_OK;
544 struct RETROWIN* win = NULL;
545 int autolock = 0;
546 ssize_t win_idx = -1;
547
548 if( !mdata_vector_is_locked( win_stack ) ) {
549 mdata_vector_lock( win_stack );
550 autolock = 1;
551 }
552
553 win_idx = retrowin_get_by_idc( idc_win, win_stack );
554 if( 0 > win_idx ) {
555 /* No window found! */
556 error_printf( "polling invalid window!" );
557 goto cleanup;
558 }
559
560 win = mdata_vector_get( win_stack, win_idx, struct RETROWIN );
561 assert( NULL != win );
562 assert( idc_win == win->idc );
563 if( !retrowin_win_is_active( win ) ) {
564 /* Window not active! */
565 error_printf( "polling inactive window!" );
566 goto cleanup;
567 }
568
569 retrowin_lock_gui( win );
570 idx_out = retrogui_get_ctl_sel_idx( win->gui_p, idc_ctl );
571 retrowin_unlock_gui( win );
572
573cleanup:
574
575 if( MERROR_OK != retval ) {
576 error_printf( "error getting window control selection index!" );
577 idx_out = merror_retval_to_sz( retval );
578 }
579
580 if( autolock ) {
581 mdata_vector_unlock( win_stack );
582 }
583
584 return idx_out;
585}
586
587/* === */
588
589void retrowin_free_win( struct RETROWIN* win ) {
590 MERROR_RETVAL retval = MERROR_OK;
591
592 if( RETROWIN_FLAG_INIT_BMP == (RETROWIN_FLAG_INIT_BMP & win->flags) ) {
593#ifndef RETROWIN_NO_BITMAP
594 retroflat_2d_destroy_bitmap( &(win->gui_bmp) );
595#endif /* !RETROWIN_NO_BITMAP */
596 retrowin_lock_gui( win );
597 win->gui_p->draw_bmp = NULL;
598 retrowin_unlock_gui( win );
599 }
600
601 if( RETROWIN_FLAG_INIT_GUI == (RETROWIN_FLAG_INIT_GUI & win->flags) ) {
602 /* This GUI was created by a NULL to push_win(). */
603 retrowin_lock_gui( win )
604 retrogui_destroy( win->gui_p );
605 retrowin_unlock_gui( win )
606 maug_mfree( win->gui_h );
607 }
608
609cleanup:
610
611 if( MERROR_OK != retval ) {
612 error_printf( "error while locking self-managed GUI! not freed!" );
613 }
614
615 maug_mzero( win, sizeof( struct RETROWIN ) );
616}
617
618/* === */
619
620MERROR_RETVAL retrowin_free_all_win( struct MDATA_VECTOR* win_stack ) {
621 MERROR_RETVAL retval = MERROR_OK;
622 struct RETROWIN* win = NULL;
623
624 if( 0 < mdata_vector_ct( win_stack ) ) {
625 mdata_vector_lock( win_stack );
626 while( 0 < mdata_vector_ct( win_stack ) ) {
627 win = mdata_vector_get( win_stack, 0, struct RETROWIN );
628 assert( NULL != win );
629 retrowin_free_win( win );
630 mdata_vector_unlock( win_stack );
631 mdata_vector_remove( win_stack, 0 );
632 mdata_vector_lock( win_stack );
633 }
634 mdata_vector_unlock( win_stack );
635 }
636 mdata_vector_free( win_stack );
637
638cleanup:
639
640 return retval;
641}
642
643/* === */
644
645ssize_t retrowin_get_by_idc(
646 retrogui_idc_t idc, struct MDATA_VECTOR* win_stack
647) {
648 ssize_t idx_out = -1;
649 int autolock = 0;
650 size_t i = 0;
651 struct RETROWIN* win = NULL;
652 MERROR_RETVAL retval = MERROR_OK;
653
654 if( 0 == mdata_vector_ct( win_stack ) ) {
655 goto cleanup;
656 }
657
658 if( !mdata_vector_is_locked( win_stack ) ) {
659 mdata_vector_lock( win_stack );
660 autolock = 1;
661 }
662
663 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
664 win = mdata_vector_get( win_stack, i, struct RETROWIN );
665 if( idc == win->idc ) {
666 idx_out = i;
667 goto cleanup;
668 }
669 }
670
671cleanup:
672
673 if( autolock ) {
674 mdata_vector_unlock( win_stack );
675 }
676
677 if( MERROR_OK != retval ) {
678 idx_out = merror_retval_to_sz( retval );
679 }
680
681 return idx_out;
682}
683
684/* === */
685
686ssize_t retrowin_push_win(
687 struct RETROGUI* gui, struct MDATA_VECTOR* win_stack,
688 retrogui_idc_t idc, const maug_path font_filename,
690 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags
691) {
692 MERROR_RETVAL retval = MERROR_OK;
693 struct RETROWIN win;
694 ssize_t idx_out = -1;
695
696 if(
697 0 > x || 0 > y ||
698 retroflat_screen_w() < x + w || retroflat_screen_h() < y + h
699 ) {
700 error_printf( "attempting to create window with IDC " RETROGUI_IDC_FMT
701 " offscreen at %d, %d (%d x %d)", idc, x, y, w, h );
702 retval = MERROR_GUI;
703 goto cleanup;
704 }
705
706 idx_out = retrowin_get_by_idc( idc, win_stack );
707 if( 0 <= idx_out ) {
708 error_printf(
709 "window with IDC " RETROGUI_IDC_FMT " already exists!", idc );
710 retval = MERROR_GUI;
711 goto cleanup;
712 }
713
714 maug_mzero( &win, sizeof( struct RETROWIN ) );
715
716 win.flags = 0;
717
718 if( NULL != gui ) {
719 win.gui_p = gui;
720 } else {
721#if RETROWIN_TRACE_LVL > 0
722 debug_printf( RETROWIN_TRACE_LVL,
723 "creating self-owned GUI for window with IDC " RETROGUI_IDC_FMT ": "
724 PXXY_FMT "x" PXXY_FMT " @ " PXXY_FMT ", " PXXY_FMT,
725 idc, w, h, x, y );
726#endif /* RETROWIN_TRACE_LVL */
727
728 win.gui_p = NULL;
729 maug_malloc_test( win.gui_h, 1, sizeof( struct RETROGUI ) );
730
731 win.flags |= RETROWIN_FLAG_INIT_GUI;
732
733 debug_printf( RETROWIN_TRACE_LVL, "x0" );
734
735 /* Prepare gui_p for use as if it had just been assigned. */
736 retrowin_lock_gui( &win );
737
738 debug_printf( RETROWIN_TRACE_LVL, "x1" );
739
740 retval = retrogui_init( win.gui_p );
741 maug_cleanup_if_not_ok();
742
743 debug_printf( RETROWIN_TRACE_LVL, "x2" );
744
745 retval = retrogui_set_font( win.gui_p, font_filename );
746 maug_cleanup_if_not_ok();
747
748 debug_printf( RETROWIN_TRACE_LVL, "x3" );
749 }
750
751#ifndef RETROWIN_NO_BITMAP
752 retval = retroflat_2d_create_bitmap( w, h, &(win.gui_bmp), 0 );
753 maug_cleanup_if_not_ok();
754#endif /* !RETROWIN_NO_BITMAP */
755
756 win.flags |= RETROWIN_FLAG_INIT_BMP;
757
758 win.gui_p->w = w;
759 win.gui_p->h = h;
760 /* These might seem redundant, but check out retrowin_redraw_win()
761 * to see how they're used.
762 */
763 win.x = x;
764 win.y = y;
765 win.gui_p->x = x;
766 win.gui_p->y = y;
767 win.idc = idc;
768 win.flags |= flags;
769
770#if RETROWIN_TRACE_LVL > 0
771 debug_printf( RETROWIN_TRACE_LVL,
772 "pushing window with IDC " RETROGUI_IDC_FMT ": "
773 PXXY_FMT "x" PXXY_FMT " @ " PXXY_FMT ", " PXXY_FMT,
774 win.idc, win.gui_p->w, win.gui_p->h, win.gui_p->x, win.gui_p->y );
775#endif /* RETROWIN_TRACE_LVL */
776
777 retrowin_unlock_gui( &win );
778
779 idx_out = mdata_vector_append( win_stack, &win, sizeof( struct RETROWIN ) );
780 if( 0 > idx_out ) {
781 goto cleanup;
782 }
783
784 if( w != h ) {
785 /* TODO: Update to detect proportional windows. */
786 error_printf(
787 "non-square window created; some systems may have trouble!" );
788 }
789
790 retrowin_refresh_win_stack( win_stack );
791
792cleanup:
793
794 /* Unlock if unlock above was skipped due to error. */
795 retrowin_unlock_gui( &win );
796
797 return idx_out;
798}
799
800/* === */
801
803 struct MDATA_VECTOR* win_stack, retrogui_idc_t idc
804) {
805 size_t i = 0;
806 MERROR_RETVAL retval = MERROR_OK;
807 struct RETROWIN* win = NULL;
808 ssize_t i_free = -1;
809 int autolock = 0;
810
811#if RETROWIN_TRACE_LVL > 0
812 debug_printf( RETROWIN_TRACE_LVL,
813 "attempting to destroy window with IDC " RETROGUI_IDC_FMT, idc );
814#endif /* RETROWIN_TRACE_LVL */
815
816 if( !mdata_vector_is_locked( win_stack ) ) {
817 mdata_vector_lock( win_stack );
818 autolock = 1;
819 }
820
821 for( i = 0 ; mdata_vector_ct( win_stack ) > i ; i++ ) {
822 win = mdata_vector_get( win_stack, i, struct RETROWIN );
823 assert( NULL != win );
824 if( idc != win->idc ) {
825 continue;
826 }
827
828 if( !retrowin_win_is_active( win ) ) {
829#if RETROWIN_TRACE_LVL > 0
830 debug_printf( RETROWIN_TRACE_LVL,
831 "window with IDC " RETROGUI_IDC_FMT
832 " found, but not active! (flags: 0x%02x)",
833 idc, win->flags );
834#endif /* RETROWIN_TRACE_LVL */
835 continue;
836 }
837
838#if RETROWIN_TRACE_LVL > 0
839 debug_printf( RETROWIN_TRACE_LVL,
840 "freeing window with IDC " RETROGUI_IDC_FMT, win->idc );
841#endif /* RETROWIN_TRACE_LVL */
842
843 retrowin_free_win( win );
844
845 i_free = i;
846
847 break;
848 }
849
850 /* Remove the window from the vector if asked to. */
851 if( 0 <= i_free ) {
852 if( autolock ) {
853 mdata_vector_unlock( win_stack );
854 }
855 mdata_vector_remove( win_stack, i_free );
856 if( autolock ) {
857 mdata_vector_lock( win_stack );
858 }
859 }
860
861cleanup:
862
863 if( autolock ) {
864 mdata_vector_unlock( win_stack );
865 }
866
867 return retval;
868}
869
870#endif /* RETROW3D_C */
871 /* maug_retrowin */
873 /* maug_retroflt */
875
876#endif /* !RETROW3D_H */
877
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:28
char maug_path[MAUG_PATH_SZ_MAX]
Path/name used to load an asset from disk or access other files.
Definition: mfile.h:141
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:374
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:879
retrogui_idc_t retrogui_poll_ctls(struct RETROGUI *gui, RETROFLAT_IN_KEY *p_input, struct RETROFLAT_INPUT *input_evt)
Poll for the last clicked control and maintain listboxes and menus.
MERROR_RETVAL retrogui_set_font(struct RETROGUI *gui, const maug_path font_path)
Load the RetroFont API for the given RETROGUI to draw its controls with. Use RetroGXCache API if avai...
MERROR_RETVAL retrogui_destroy(struct RETROGUI *gui)
Free memory held by a RETROGUI controller internally and clean up any subordinate controls.
MERROR_RETVAL retrogui_init(struct RETROGUI *gui)
Prepare a RETROGUI controller for use.
int16_t retrogui_idc_t
Unique identifying constant number for controls.
Definition: retrogui.h:330
#define RETROGUI_COLOR_BORDER
RetroGUI will try to use this color on non-monochrome systems instead of black to draw things like bo...
Definition: retrogui.h:93
retrogui_idc_t retrowin_poll_win_stack(struct MDATA_VECTOR *win_stack, retrogui_idc_t idc_active, RETROFLAT_IN_KEY *p_input, struct RETROFLAT_INPUT *input_evt)
Given the outputs of the input poller, check the controls on the active window to see if the inputs t...
MERROR_RETVAL retrowin_refresh_win_stack(struct MDATA_VECTOR *win_stack)
Force all windows on the stack to redraw.
MERROR_RETVAL retrowin_destroy_win(struct MDATA_VECTOR *win_stack, retrogui_idc_t idc)
Destroy the given window's resources and remove it from the window stack.
ssize_t retrowin_get_win_stack_sel_idx(struct MDATA_VECTOR *win_stack, retrogui_idc_t idc_win, retrogui_idc_t idc_ctl)
Get the selected index of the given control in the given window from the window stack.
ssize_t retrowin_push_win(struct RETROGUI *gui, struct MDATA_VECTOR *win_stack, retrogui_idc_t idc, const maug_path font_filename, retroflat_pxxy_t x, retroflat_pxxy_t y, retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags)
Create a new window on the given win_stack.
ssize_t mdata_vector_append(struct MDATA_VECTOR *v, const void *item, size_t item_sz)
Append an item to the specified vector.
MERROR_RETVAL mdata_vector_remove(struct MDATA_VECTOR *v, size_t idx)
Remove item at the given index, shifting subsequent items up by 1.
A vector of uniformly-sized objects, stored contiguously.
Definition: mdata.h:108
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:372
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:405
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:448
Struct passed to retroflat_poll_input() to hold return data.
Definition: retroflt.h:823
Definition: retrogui.h:468
#define RETROGUI_FLAGS_DIRTY
RETROGUI::flags indicating controls should be redrawn.
Definition: retrogui.h:263
Definition: retrowin.h:99
#define RETROWIN_FLAG_INIT_GUI
Flag for RETROWIN::flags indicating RETROWIN::gui_p should be locked from RETROWIN::gui_h before use.
Definition: retrowin.h:58