79#ifndef RETROFONT_PRESENT
80# error "retrofont not present!"
85#ifndef RETROGUI_TRACE_LVL
86# define RETROGUI_TRACE_LVL 0
89#ifndef RETROGUI_COLOR_BORDER
95# define RETROGUI_COLOR_BORDER RETROFLAT_COLOR_DARKBLUE
98#ifndef RETROGUI_CTL_TEXT_SZ_MAX
105#ifndef RETROGUI_KEY_ACTIVATE
111# define RETROGUI_KEY_ACTIVATE RETROFLAT_KEY_SPACE
114#ifndef RETROGUI_KEY_NEXT
120# define RETROGUI_KEY_NEXT RETROFLAT_KEY_DOWN
123#ifndef RETROGUI_KEY_PREV
129# define RETROGUI_KEY_PREV RETROFLAT_KEY_UP
132#ifndef RETROGUI_KEY_SEL_NEXT
138# define RETROGUI_KEY_SEL_NEXT RETROFLAT_KEY_RIGHT
141#ifndef RETROGUI_KEY_SEL_PREV
147# define RETROGUI_KEY_SEL_PREV RETROFLAT_KEY_LEFT
150#ifndef RETROGUI_PAD_ACTIVATE
156# define RETROGUI_PAD_ACTIVATE RETROFLAT_PAD_A
159#ifndef RETROGUI_PAD_NEXT
165# define RETROGUI_PAD_NEXT RETROFLAT_PAD_DOWN
168#ifndef RETROGUI_PAD_PREV
174# define RETROGUI_PAD_PREV RETROFLAT_PAD_UP
177#ifndef RETROGUI_PAD_SEL_NEXT
183# define RETROGUI_PAD_SEL_NEXT RETROFLAT_PAD_RIGHT
186#ifndef RETROGUI_PAD_SEL_PREV
192# define RETROGUI_PAD_SEL_PREV RETROFLAT_PAD_LEFT
195# define RETROGUI_CTL_TEXT_SZ_MAX 128
198#ifndef RETROGUI_CTL_SZ_MAX_INIT
199# define RETROGUI_CTL_SZ_MAX_INIT 20
202#ifndef RETROGUI_PADDING
207# define RETROGUI_PADDING 5
210#ifndef RETROGUI_BTN_LBL_SZ_MAX
211# define RETROGUI_BTN_LBL_SZ_MAX 64
214#ifndef RETROGUI_BTN_LBL_PADDED_X
215# define RETROGUI_BTN_LBL_PADDED_X 8
218#ifndef RETROGUI_BTN_LBL_PADDED_Y
219# define RETROGUI_BTN_LBL_PADDED_Y 8
222#ifndef RETROGUI_CTL_TEXT_BLINK_FRAMES
223# define RETROGUI_CTL_TEXT_BLINK_FRAMES 15
226#ifndef RETROGUI_CTL_LISTBOX_CURSOR_RADIUS
227# define RETROGUI_CTL_LISTBOX_CURSOR_RADIUS 8
230#ifndef RETROGUI_CTL_LISTBOX_STR_SZ_MAX
231# define RETROGUI_CTL_LISTBOX_STR_SZ_MAX 255
234#ifndef RETROGUI_CTL_TEXT_CUR_WH
235# define RETROGUI_CTL_TEXT_CUR_WH 8
238#ifndef RETROGUI_DEBOUNCE_MAX_DEFAULT
239# define RETROGUI_DEBOUNCE_MAX_DEFAULT 100
248#define RETROGUI_FLAGS_DIRTY 0x01
255#define RETROGUI_FLAGS_FONT_OWNED 0x02
257#define RETROGUI_FILLBAR_FLAG_SHOWNUM 0x02
259#define _retrogui_copy_str( field, src_str, dest_ctl, str_tmp, str_sz ) \
261 assert( NULL != src_str ); \
262 debug_printf( RETROGUI_TRACE_LVL, \
263 "copying string \"%s\" to " #dest_ctl, src_str ); \
264 if( 0 == str_sz ) { \
265 str_sz = maug_strlen( src_str ); \
266 debug_printf( RETROGUI_TRACE_LVL, \
267 "determined str sz of \"%s\": " SIZE_T_FMT, src_str, str_sz ); \
269 if( (MAUG_MHANDLE)NULL != dest_ctl. field ## _h ) { \
271 maug_mfree( dest_ctl. field ## _h ); \
275 dest_ctl. field ## _h = maug_malloc( str_sz + 1, 1 ); \
276 debug_printf( RETROGUI_TRACE_LVL, \
277 "allocated str sz for \"%s\": " SIZE_T_FMT, src_str, str_sz + 1 ); \
278 maug_cleanup_if_null_alloc( MAUG_MHANDLE, dest_ctl. field ## _h ); \
279 maug_mlock( dest_ctl. field ## _h, str_tmp ); \
280 maug_cleanup_if_null_lock( char*, str_tmp ); \
283 assert( NULL != str_tmp ); \
284 maug_mzero( str_tmp, str_sz + 1 ); \
285 debug_printf( RETROGUI_TRACE_LVL, \
286 "zeroed str sz for \"%s\": " SIZE_T_FMT, src_str, str_sz + 1 ); \
287 maug_strncpy( str_tmp, src_str, str_sz ); \
288 debug_printf( RETROGUI_TRACE_LVL, "copied str as: \"%s\"", str_tmp ); \
289 maug_munlock( dest_ctl. field ## _h, str_tmp );
294#define RETROGUI_IDC_FMT "%d"
296#define RETROGUI_IDC_NONE -1
301#define RETROGUI_COLOR_BG 1
306#define RETROGUI_COLOR_FG 2
312#define RETROGUI_COLOR_SEL_BG 3
318#define RETROGUI_COLOR_SEL_FG 4
343#define RETROGUI_CTL_TABLE_BASE( f ) \
344 f( 0, NONE, void* none; ) \
345 f( 1, LISTBOX, struct MDATA_VECTOR list; size_t sel_idx; ) \
346 f( 2, BUTTON, MAUG_MHANDLE label_h; char* label; size_t label_sz; int16_t push_frames; uint8_t font_flags; ) \
347 f( 3, LABEL, MAUG_MHANDLE label_h; char* label; size_t label_sz; uint8_t font_flags; ) \
348 f( 4, IMAGE, retroflat_blit_t image; ssize_t image_cache_id; int16_t instance; retroflat_pxxy_t src_x; retroflat_pxxy_t src_y; ) \
349 f( 5, FILLBAR, uint8_t flags; uint16_t cur; uint16_t max; )
351#ifdef RETROGUI_NO_TEXTBOX
352# define RETROGUI_CTL_TABLE( f ) RETROGUI_CTL_TABLE_BASE( f )
354# define RETROGUI_CTL_TABLE( f ) RETROGUI_CTL_TABLE_BASE( f ) \
355 f( 6, TEXTBOX, MAUG_MHANDLE text_h; char* text; size_t text_sz; size_t text_sz_max; size_t text_cur; int16_t blink_frames; )
359 f( 6, SCROLLBAR,
size_t min;
size_t max;
size_t value; )
362#ifdef RETROGUI_NO_TEXTBOX
364 (RETROGUI_CTL_TYPE_BUTTON == (ctl)->base.type || \
365 RETROGUI_CTL_TYPE_LISTBOX == (ctl)->base.type)
371 (RETROGUI_CTL_TYPE_BUTTON == (ctl)->base.type || \
372 RETROGUI_CTL_TYPE_TEXTBOX == (ctl)->base.type || \
373 RETROGUI_CTL_TYPE_LISTBOX == (ctl)->base.type)
388#if defined( RETROGUI_NATIVE_WIN )
397#define RETROGUI_CTL_TABLE_FIELDS( idx, c_name, c_fields ) \
398 struct RETROGUI_CTL_ ## c_name { \
399 struct RETROGUI_CTL_BASE base; \
409#define RETROGUI_CTL_TABLE_TYPES( idx, c_name, c_fields ) \
410 struct RETROGUI_CTL_ ## c_name c_name;
419typedef void (*retrogui_xy_cb)(
422typedef char retrogui_list_t[RETROGUI_CTL_LISTBOX_STR_SZ_MAX + 1];
441 retroflat_blit_t* draw_bmp;
442 retroflat_ms_t debounce_next;
443 retroflat_ms_t debounce_max;
444#ifdef RETROGXC_PRESENT
472 struct RETROGUI* gui, RETROFLAT_IN_KEY* p_input,
498 struct RETROGUI* gui,
const char* font_path );
500#ifndef RETROGUI_NO_TEXTBOX
515 const char* fmt, ... );
564 struct RETROGUI* gui,
size_t start, ssize_t incr );
602#define retrogui_focus_next( gui ) \
603 retrogui_focus_iter( gui, 0, 1 )
605#define retrogui_focus_prev( gui ) \
606 retrogui_focus_iter( gui, mdata_vector_ct( &((gui)->ctls) ) - 1, -1 )
610#define RETROGUI_CTL_TABLE_CONSTS( idx, c_name, c_fields ) \
611 MAUG_CONST uint8_t SEG_MCONST RETROGUI_CTL_TYPE_ ## c_name = idx;
613RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_CONSTS )
615#ifdef RETROGUI_TRACE_TOKENS
617#define RETROGUI_CTL_TABLE_NAMES( idx, c_name, f_fields ) \
620MAUG_CONST
char* SEG_MCONST gc_retrogui_ctl_names[] = {
621 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_NAMES )
676static void retrogui_destroy_NONE(
union RETROGUI_CTL* ctl ) {
700# if defined( RETROGUI_NATIVE_WIN )
704 if( !mdata_vector_is_locked( &(ctl->LISTBOX.list) ) ) {
712 (
char*)mdata_vector_get( &(ctl->LISTBOX.list), i, retrogui_list_t );
715#ifdef RETROGXC_PRESENT
717 gui->draw_bmp, list_i, 0, gui->font_idx,
718 ctl->base.w, ctl->base.h, &w, &h, 0 );
721 gui->draw_bmp, list_i, 0, gui->
font_h,
722 ctl->base.w, ctl->base.h, &w, &h, 0 );
729 ctl->LISTBOX.sel_idx = i;
742 if( MERROR_OK != retval ) {
743 idc_out = RETROGUI_IDC_NONE;
759 ctl->LISTBOX.sel_idx++;
760 if( ctl->LISTBOX.sel_idx >=
mdata_vector_ct( &(ctl->LISTBOX.list) ) ) {
761 ctl->LISTBOX.sel_idx = 0;
770 ctl->LISTBOX.sel_idx--;
772 if( ctl->LISTBOX.sel_idx >=
mdata_vector_ct( &(ctl->LISTBOX.list) ) ) {
785static void retrogui_redraw_LISTBOX(
797# if defined( RETROGUI_NATIVE_WIN )
801 if( !mdata_vector_is_locked( &(ctl->LISTBOX.list) ) ) {
806 if( RETROFLAT_COLOR_BLACK != ctl->base.bg_color ) {
807 retroflat_2d_rect( gui->draw_bmp, ctl->base.bg_color,
808 gui->x + ctl->base.x, gui->y + ctl->base.y,
814 (
char*)mdata_vector_get( &(ctl->LISTBOX.list), i, retrogui_list_t );
815#ifdef RETROGXC_PRESENT
817 gui->draw_bmp, list_i, 0, gui->font_idx,
818 ctl->base.w, ctl->base.h, &w, &h, 0 );
821 gui->draw_bmp, list_i, 0, gui->
font_h,
822 ctl->base.w, ctl->base.h, &w, &h, 0 );
824#if RETROGUI_TRACE_LVL > 0
825 debug_printf( RETROGUI_TRACE_LVL,
826 "str height for \"%s\": " SIZE_T_FMT, list_i, h );
828 if( i == ctl->LISTBOX.sel_idx ) {
830 retroflat_2d_rect( gui->draw_bmp, ctl->base.sel_bg,
831 gui->x + ctl->base.x,
832 gui->y + ctl->base.y + item_y,
834 fg_color = ctl->base.sel_fg;
836 retroflat_2d_ellipse(
837 gui->draw_bmp, ctl->base.sel_fg,
838 gui->x + ctl->base.x,
839 gui->y + ctl->base.y + item_y,
840 RETROGUI_CTL_LISTBOX_CURSOR_RADIUS,
841 RETROGUI_CTL_LISTBOX_CURSOR_RADIUS, 0 );
844 fg_color = ctl->base.fg_color;
847#ifdef RETROGXC_PRESENT
849 gui->draw_bmp, fg_color, list_i, 0, gui->font_idx,
850 gui->x + ctl->base.x +
852 gui->y + ctl->base.y + item_y,
856 gui->draw_bmp, fg_color, list_i, 0, gui->
font_h,
857 gui->x + ctl->base.x +
859 gui->y + ctl->base.y + item_y,
874 assert( MERROR_OK == retval );
885# if defined( RETROGUI_NATIVE_WIN )
888 SendMessage( ctl->base.hwnd, LB_SETCURSEL, item_idx, 0 );
892 ctl->LISTBOX.sel_idx = item_idx;
905 retrogui_list_t item_stage;
908 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
913#if RETROGUI_TRACE_LVL > 0
914 debug_printf( RETROGUI_TRACE_LVL,
915 "pushing item \"%s\" to listbox " RETROGUI_IDC_FMT
"...", item, idc );
918 ctl = _retrogui_get_ctl_by_idc( gui, idc );
921 error_printf(
"could not add item: %s", item );
926# if defined( RETROGUI_NATIVE_WIN )
928 SendMessage( ctl->LISTBOX.base.hwnd, LB_ADDSTRING, 0, (LPARAM)item );
932 maug_mzero( item_stage, RETROGUI_CTL_LISTBOX_STR_SZ_MAX + 1 );
933 maug_strncpy( item_stage, item, RETROGUI_CTL_LISTBOX_STR_SZ_MAX );
935 &(ctl->LISTBOX.list), item_stage, RETROGUI_CTL_LISTBOX_STR_SZ_MAX + 1 );
937 retval = merror_sz_to_retval( i );
956# if defined( RETROGUI_NATIVE_WIN )
958 ctl->base.hwnd = CreateWindow(
959 "LISTBOX", NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD,
960 gui->x + ctl->base.x, gui->y + ctl->base.y, ctl->base.w, ctl->base.h,
961 g_retroflat_state->window, (HMENU)(ctl->base.idc),
962 g_retroflat_instance, NULL );
963#if RETROGUI_TRACE_LVL > 0
964 debug_printf( RETROGUI_TRACE_LVL,
965 "listbox hwnd: %p", ctl->LISTBOX.base.hwnd );
967 if( (HWND)NULL == ctl->base.hwnd ) {
968 error_printf(
"could not create listbox" );
1006static void retrogui_destroy_LISTBOX(
union RETROGUI_CTL* ctl ) {
1007 mdata_vector_free( &(ctl->LISTBOX.list) );
1013#if RETROGUI_TRACE_LVL > 0
1014 debug_printf( RETROGUI_TRACE_LVL,
1015 "initializing listbox " RETROGUI_IDC_FMT
"...", ctl->base.idc );
1018 ctl->base.bg_color = RETROFLAT_COLOR_WHITE;
1019 ctl->base.sel_fg = RETROFLAT_COLOR_WHITE;
1020 if( 2 < retroflat_screen_colors() ) {
1021 ctl->base.sel_bg = RETROFLAT_COLOR_BLUE;
1024 ctl->base.sel_bg = RETROFLAT_COLOR_BLACK;
1025 ctl->base.fg_color = RETROFLAT_COLOR_BLACK;
1040 if( 0 < ctl->BUTTON.push_frames ) {
1045 idc_out = ctl->base.idc;
1049 ctl->BUTTON.push_frames = 3;
1069static void retrogui_redraw_BUTTON(
1080 if( ctl->base.idc == gui->
focus ) {
1082 fg_color = ctl->base.sel_fg;
1085 if( ctl->base.idc == gui->
focus ) {
1087 bg_color = ctl->base.sel_bg;
1091 if( 2 >= retroflat_screen_colors() ) {
1092 push_shadow_color = RETROFLAT_COLOR_BLACK;
1093 border_color = RETROFLAT_COLOR_BLACK;
1097 gui->draw_bmp, bg_color, ctl->base.x, ctl->base.y,
1100 retroflat_2d_rect( gui->draw_bmp, border_color,
1101 gui->x + ctl->base.x, gui->y + ctl->base.y,
1102 ctl->base.w, ctl->base.h, 0 );
1107 if( 0 < ctl->BUTTON.push_frames ) {
1109 gui->draw_bmp, push_shadow_color,
1110 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + 1,
1111 gui->x + ctl->base.x + ctl->base.w - 2, gui->y + ctl->base.y + 1, 0 );
1113 gui->draw_bmp, push_shadow_color,
1114 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + 2,
1115 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + ctl->base.h - 3, 0 );
1118 ctl->BUTTON.push_frames--;
1123 gui->draw_bmp, RETROFLAT_COLOR_WHITE,
1124 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + 1,
1125 gui->x + ctl->base.x + ctl->base.w - 2, gui->y + ctl->base.y + 1, 0 );
1127 gui->draw_bmp, RETROFLAT_COLOR_WHITE,
1128 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + 2,
1129 gui->x + ctl->base.x + 1, gui->y + ctl->base.y + ctl->base.h - 3, 0 );
1132 maug_mlock( ctl->BUTTON.label_h, ctl->BUTTON.label );
1133 if( NULL == ctl->BUTTON.label ) {
1134 error_printf(
"could not lock BUTTON label!" );
1139#ifdef RETROGXC_PRESENT
1142 retrofont_string_sz(
1144 gui->draw_bmp, ctl->BUTTON.label, 0,
1145#ifdef RETROGXC_PRESENT
1151 ctl->base.w, ctl->base.h, &w, &h, ctl->BUTTON.font_flags );
1153#ifdef RETROGXC_PRESENT
1158 gui->draw_bmp, fg_color, ctl->BUTTON.label, 0,
1159#ifdef RETROGXC_PRESENT
1164 gui->x + ctl->base.x + ((ctl->base.w >> 1) - (w >> 1)) + text_offset,
1165 gui->y + ctl->base.y + ((ctl->base.h >> 1) - (h >> 1)) + text_offset,
1167 ctl->base.w, ctl->base.h, ctl->BUTTON.font_flags );
1169 maug_munlock( ctl->BUTTON.label_h, ctl->BUTTON.label );
1179# if defined( RETROGUI_NATIVE_WIN )
1181 ctl->base.hwnd = CreateWindow(
1182 "BUTTON", ctl->BUTTON.label, WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1183 gui->x + ctl->base.x, gui->y + ctl->base.y, ctl->base.w, ctl->base.h,
1184 g_retroflat_state->window, (HMENU)(ctl->base.idc),
1185 g_retroflat_instance, NULL );
1186 if( (HWND)NULL == ctl->base.hwnd ) {
1188 "Could not create button " RETROGUI_IDC_FMT
": %s",
1189 ctl->base.idc, ctl->BUTTON.label );
1190 retval = MERROR_GUI;
1195 size_t label_sz = 0;
1196 char* label_tmp = NULL;
1198#if RETROGUI_TRACE_LVL > 0
1199 debug_printf( RETROGUI_TRACE_LVL,
"pushing BUTTON control..." );
1203 label, ctl->BUTTON.label, ctl->BUTTON, label_tmp, label_sz );
1204 ctl->BUTTON.label = NULL;
1219 assert( NULL != ctl );
1220 assert( NULL == ctl->BUTTON.label );
1221 assert( (MAUG_MHANDLE)NULL != ctl->BUTTON.label_h );
1223 maug_mlock( ctl->BUTTON.label_h, ctl->BUTTON.label );
1224 maug_cleanup_if_null_lock(
char*, ctl->BUTTON.label );
1227#ifdef RETROGXC_PRESENT
1230 retrofont_string_sz(
1235#ifdef RETROGXC_PRESENT
1243 p_h, ctl->BUTTON.font_flags );
1246 *p_w += RETROGUI_BTN_LBL_PADDED_X;
1247 *p_h += RETROGUI_BTN_LBL_PADDED_Y;
1251 maug_munlock( ctl->BUTTON.label_h, ctl->BUTTON.label );
1263# if defined( RETROGUI_NATIVE_WIN )
1266 assert( NULL != ctl );
1281static void retrogui_destroy_BUTTON(
union RETROGUI_CTL* ctl ) {
1282 if( (MAUG_MHANDLE)NULL != ctl->BUTTON.label_h ) {
1283 maug_mfree( ctl->BUTTON.label_h );
1290#if RETROGUI_TRACE_LVL > 0
1291 debug_printf( RETROGUI_TRACE_LVL,
1292 "initializing button " RETROGUI_IDC_FMT
"...", ctl->base.idc );
1295 if( 2 < retroflat_screen_colors() ) {
1297 ctl->base.bg_color = RETROFLAT_COLOR_GRAY;
1298 ctl->base.sel_fg = RETROFLAT_COLOR_BLUE;
1299 ctl->base.sel_bg = RETROFLAT_COLOR_GRAY;
1301 ctl->base.fg_color = RETROFLAT_COLOR_BLACK;
1302 ctl->base.bg_color = RETROFLAT_COLOR_WHITE;
1303 ctl->base.sel_fg = RETROFLAT_COLOR_WHITE;
1304 ctl->base.sel_bg = RETROFLAT_COLOR_BLACK;
1310#ifndef RETROGUI_NO_TEXTBOX
1331# if defined( RETROGUI_NATIVE_WIN )
1335 c = retroflat_vk_to_ascii( *p_input, input_evt->key_flags );
1340 RETROFLAT_KEY_RIGHT != *p_input &&
1341 RETROFLAT_KEY_LEFT != *p_input
1347 assert( NULL == ctl->TEXTBOX.text );
1348 assert( (MAUG_MHANDLE)NULL != ctl->TEXTBOX.text_h );
1349 maug_mlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1350 if( NULL == ctl->TEXTBOX.text ) {
1351 error_printf(
"could not lock TEXTBOX text handle!" );
1355 switch( *p_input ) {
1356 case RETROFLAT_KEY_BKSP:
1358 ctl->TEXTBOX.text, ctl->TEXTBOX.text_cur, ctl->TEXTBOX.text_sz )
1361 case RETROFLAT_KEY_ENTER:
1362 idc_out = ctl->base.idc;
1365 case RETROFLAT_KEY_LEFT:
1366 if( 0 < ctl->TEXTBOX.text_cur ) {
1367 ctl->TEXTBOX.text_cur--;
1371 case RETROFLAT_KEY_RIGHT:
1372 if( ctl->TEXTBOX.text_sz > ctl->TEXTBOX.text_cur ) {
1373 ctl->TEXTBOX.text_cur++;
1378 assert( ctl->TEXTBOX.text_sz < ctl->TEXTBOX.text_sz_max );
1381 ctl->TEXTBOX.text_cur,
1382 ctl->TEXTBOX.text_sz,
1383 ctl->TEXTBOX.text_sz_max );
1391 if( NULL != ctl->TEXTBOX.text ) {
1392 maug_munlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1400static void retrogui_redraw_TEXTBOX(
1409 if( 2 >= retroflat_screen_colors() ) {
1410 shadow_color = RETROFLAT_COLOR_BLACK;
1411 border_color = RETROFLAT_COLOR_BLACK;
1414# if defined( RETROGUI_NATIVE_WIN )
1418 retroflat_2d_rect( gui->draw_bmp, ctl->base.bg_color,
1419 gui->x + ctl->base.x, gui->y + ctl->base.y,
1424 retroflat_2d_rect( gui->draw_bmp, border_color,
1425 gui->x + ctl->base.x,
1426 gui->y + ctl->base.y, ctl->base.w, 2,
1429 retroflat_2d_rect( gui->draw_bmp, border_color,
1430 gui->x + ctl->base.x,
1431 gui->y + ctl->base.y, 2, ctl->base.h,
1434 retroflat_2d_rect( gui->draw_bmp, shadow_color,
1435 gui->x + ctl->base.x,
1436 gui->y + ctl->base.y + ctl->base.h - 1,
1440 retroflat_2d_rect( gui->draw_bmp, shadow_color,
1441 gui->x + ctl->base.x + ctl->base.w - 1,
1442 gui->y + ctl->base.y, 2, ctl->base.h,
1447 assert( NULL == ctl->TEXTBOX.text );
1448 maug_mlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1449 if( NULL == ctl->TEXTBOX.text ) {
1453#ifdef RETROGXC_PRESENT
1455 gui->draw_bmp, ctl->base.fg_color,
1456 ctl->TEXTBOX.text, ctl->TEXTBOX.text_cur, gui->font_idx,
1462 gui->draw_bmp, ctl->TEXTBOX.text, ctl->TEXTBOX.text_cur, gui->font_idx,
1466 gui->draw_bmp, ctl->base.fg_color,
1467 ctl->TEXTBOX.text, ctl->TEXTBOX.text_cur, gui->
font_h,
1472 retrofont_string_sz(
1473 gui->draw_bmp, ctl->TEXTBOX.text, ctl->TEXTBOX.text_cur, gui->
font_h,
1479 if( cursor_x + RETROGUI_CTL_TEXT_CUR_WH >= ctl->base.w ) {
1482 cursor_y += RETROGUI_CTL_TEXT_CUR_WH;
1486 retroflat_2d_rect( gui->draw_bmp,
1490 RETROGUI_CTL_TEXT_CUR_WH, RETROGUI_CTL_TEXT_CUR_WH,
1493 gui->
focus == ctl->base.idc &&
1496 if( (-1 * RETROGUI_CTL_TEXT_BLINK_FRAMES) > --(ctl->TEXTBOX.blink_frames) ) {
1497 ctl->TEXTBOX.blink_frames = RETROGUI_CTL_TEXT_BLINK_FRAMES;
1500 if( NULL != ctl->TEXTBOX.text ) {
1502 #ifdef RETROGXC_PRESENT
1503 retrogxc_string_indent(
1504 gui->draw_bmp, ctl->base.fg_color,
1505 &(ctl->TEXTBOX.text[ctl->TEXTBOX.text_cur]),
1507 strlen( ctl->TEXTBOX.text ) - ctl->TEXTBOX.text_cur,
1512 ctl->base.w, ctl->base.h,
1513 cursor_x + RETROGUI_CTL_TEXT_CUR_WH, 0 );
1515 retrofont_string_indent(
1516 gui->draw_bmp, ctl->base.fg_color,
1517 &(ctl->TEXTBOX.text[ctl->TEXTBOX.text_cur]),
1519 strlen( ctl->TEXTBOX.text ) - ctl->TEXTBOX.text_cur,
1524 ctl->base.w, ctl->base.h,
1525 cursor_x + RETROGUI_CTL_TEXT_CUR_WH, 0 );
1528 maug_munlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1541# if defined( RETROGUI_NATIVE_WIN )
1543 ctl->base.hwnd = CreateWindow(
1544 "EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER,
1545 gui->x + ctl->base.x, gui->y + ctl->base.y, ctl->base.w, ctl->base.h,
1546 g_retroflat_state->window, (HMENU)(ctl->base.idc),
1547 g_retroflat_instance, NULL );
1548 if( (HWND)NULL == ctl->base.hwnd ) {
1550 "Could not create textbox: " RETROGUI_IDC_FMT, ctl->base.idc );
1551 retval = MERROR_GUI;
1557#if RETROGUI_TRACE_LVL > 0
1558 debug_printf( RETROGUI_TRACE_LVL,
1559 "clearing textbox " RETROGUI_IDC_FMT
" buffer...", ctl->base.idc );
1561 assert( (MAUG_MHANDLE)NULL == ctl->TEXTBOX.text_h );
1562 ctl->TEXTBOX.text_h = maug_malloc( RETROGUI_CTL_TEXT_SZ_MAX + 1, 1 );
1563 maug_cleanup_if_null_alloc( MAUG_MHANDLE, ctl->TEXTBOX.text_h );
1564 ctl->TEXTBOX.text_sz_max = RETROGUI_CTL_TEXT_SZ_MAX;
1566 maug_mlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1567 maug_cleanup_if_null_alloc(
char*, ctl->TEXTBOX.text );
1568#if RETROGUI_TRACE_LVL > 0
1569 debug_printf( RETROGUI_TRACE_LVL,
1570 "clearing textbox " RETROGUI_IDC_FMT
" buffer...", ctl->base.idc );
1572 maug_mzero( ctl->TEXTBOX.text, RETROGUI_CTL_TEXT_SZ_MAX + 1 );
1573 maug_munlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
1602static void retrogui_destroy_TEXTBOX(
union RETROGUI_CTL* ctl ) {
1603 if( (MAUG_MHANDLE)NULL != ctl->TEXTBOX.text_h ) {
1604 maug_mfree( ctl->TEXTBOX.text_h );
1611#if RETROGUI_TRACE_LVL > 0
1612 debug_printf( RETROGUI_TRACE_LVL,
1613 "initializing textbox " RETROGUI_IDC_FMT
"...", ctl->base.idc );
1616 ctl->base.bg_color = RETROFLAT_COLOR_WHITE;
1617 ctl->base.sel_bg = RETROFLAT_COLOR_WHITE;
1618 if( 2 < retroflat_screen_colors() ) {
1619 ctl->base.sel_fg = RETROFLAT_COLOR_BLUE;
1622 ctl->base.sel_fg = RETROFLAT_COLOR_BLACK;
1623 ctl->base.fg_color = RETROFLAT_COLOR_BLACK;
1638 return RETROGUI_IDC_NONE;
1645 return RETROGUI_IDC_NONE;
1648static void retrogui_redraw_LABEL(
1652# if defined( RETROGUI_NATIVE_WIN )
1658#ifdef RETROGXC_PRESENT
1659 assert( 0 <= gui->font_idx );
1661 assert( (MAUG_MHANDLE)NULL != gui->
font_h );
1664 assert( NULL == ctl->LABEL.label );
1665 maug_mlock( ctl->LABEL.label_h, ctl->LABEL.label );
1666 if( NULL == ctl->LABEL.label ) {
1667 error_printf(
"could not lock LABEL text!" );
1671#ifdef RETROGXC_PRESENT
1676 gui->draw_bmp, ctl->base.fg_color, ctl->LABEL.label,
1677 ctl->LABEL.label_sz,
1678#ifdef RETROGXC_PRESENT
1685 ctl->LABEL.font_flags );
1689 if( NULL != ctl->LABEL.label ) {
1690 maug_munlock( ctl->LABEL.label_h, ctl->LABEL.label );
1701# if defined( RETROGUI_NATIVE_WIN )
1706 size_t label_sz = 0;
1707 char* label_tmp = NULL;
1709#if RETROGUI_TRACE_LVL > 0
1710 debug_printf( RETROGUI_TRACE_LVL,
"pushing LABEL control..." );
1714 label, ctl->LABEL.label, ctl->LABEL, label_tmp, label_sz );
1715 ctl->LABEL.label = NULL;
1743static void retrogui_destroy_LABEL(
union RETROGUI_CTL* ctl ) {
1744 if( (MAUG_MHANDLE)NULL != ctl->LABEL.label_h ) {
1745 maug_mfree( ctl->LABEL.label_h );
1752#if RETROGUI_TRACE_LVL > 0
1753 debug_printf( RETROGUI_TRACE_LVL,
1754 "initializing label " RETROGUI_IDC_FMT
"...", ctl->base.idc );
1757 if( 2 < retroflat_screen_colors() ) {
1760 ctl->base.fg_color = RETROFLAT_COLOR_BLACK;
1762 ctl->base.bg_color = RETROFLAT_COLOR_WHITE;
1774 return RETROGUI_IDC_NONE;
1781 return RETROGUI_IDC_NONE;
1784static void retrogui_redraw_IMAGE(
1787# if defined( RETROGUI_NATIVE_WIN )
1791# if defined( RETROGXC_PRESENT )
1792 if( 0 <= ctl->IMAGE.image_cache_id ) {
1795#if RETROGUI_TRACE_LVL > 0
1796 debug_printf( RETROGUI_TRACE_LVL,
1797 "redrawing image ctl " RETROGUI_IDC_FMT
1798 ", cache ID " SSIZE_T_FMT
"...",
1799 ctl->base.idc, ctl->IMAGE.image_cache_id );
1801 retrogxc_blit_bitmap(
1803 ctl->IMAGE.image_cache_id,
1804 ctl->IMAGE.src_x, ctl->IMAGE.src_y,
1805 gui->x + ctl->base.x, gui->y + ctl->base.y, ctl->base.w, ctl->base.h,
1806 ctl->IMAGE.instance );
1809 if( retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) ) ) {
1811 retroflat_2d_blit_bitmap(
1813 &(ctl->IMAGE.image),
1814 ctl->IMAGE.src_x, ctl->IMAGE.src_y,
1815 gui->x + ctl->base.x, gui->y + ctl->base.y, ctl->base.w, ctl->base.h,
1816 ctl->IMAGE.instance );
1827# if defined( RETROGUI_NATIVE_WIN )
1833#if RETROGUI_TRACE_LVL > 0
1834 debug_printf( RETROGUI_TRACE_LVL,
"pushing IMAGE control..." );
1837 assert( !retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) ) );
1857# ifdef RETROGXC_PRESENT
1858 retval = retrogxc_bitmap_wh( ctl->IMAGE.image_cache_id, p_w, p_h );
1859 maug_cleanup_if_not_ok();
1863 0 == *p_w && 0 == *p_h &&
1864 !retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) )
1866 error_printf(
"image not assigned!" );
1867 retval = MERROR_GUI;
1871 *p_w = retroflat_2d_bitmap_w( &(ctl->IMAGE.image) );
1872 *p_h = retroflat_2d_bitmap_h( &(ctl->IMAGE.image) );
1889static void retrogui_destroy_IMAGE(
union RETROGUI_CTL* ctl ) {
1890 if( retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) ) ) {
1891 retroflat_2d_destroy_bitmap( &(ctl->IMAGE.image) );
1898#if RETROGUI_TRACE_LVL > 0
1899 debug_printf( RETROGUI_TRACE_LVL,
1900 "initializing IMAGE " RETROGUI_IDC_FMT
"...", ctl->base.idc );
1927static void retrogui_redraw_FILLBAR(
1932 if( 0 == ctl->FILLBAR.cur ) {
1935 fill_w = ctl->base.w * ctl->FILLBAR.cur / ctl->FILLBAR.max;
1939 gui->draw_bmp, ctl->base.bg_color, ctl->base.x + fill_w, ctl->base.y,
1943 gui->draw_bmp, ctl->base.fg_color, ctl->base.x, ctl->base.y,
1952# if defined( RETROGUI_NATIVE_WIN )
1968 assert( NULL != ctl );
1982# if defined( RETROGUI_NATIVE_WIN )
1985 assert( NULL != ctl );
2000static void retrogui_destroy_FILLBAR(
union RETROGUI_CTL* ctl ) {
2006#if RETROGUI_TRACE_LVL > 0
2007 debug_printf( RETROGUI_TRACE_LVL,
2008 "initializing fillbar " RETROGUI_IDC_FMT
"...", ctl->base.idc );
2011 if( 2 < retroflat_screen_colors() ) {
2013 ctl->base.bg_color = RETROFLAT_COLOR_GRAY;
2015 ctl->base.fg_color = RETROFLAT_COLOR_BLACK;
2016 ctl->base.bg_color = RETROFLAT_COLOR_WHITE;
2030 assert( mdata_vector_is_locked( &((gui)->ctls) ) );
2033 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
2034 if( idc == ctl->base.idc ) {
2041 error_printf(
"could not find GUI item IDC " RETROGUI_IDC_FMT, idc );
2057 assert( mdata_vector_is_locked( &((gui)->ctls) ) );
2059#if RETROGUI_TRACE_LVL > 0
2060 debug_printf( RETROGUI_TRACE_LVL,
2061 "sizing control " RETROGUI_IDC_FMT
" to: " SIZE_T_FMT
"x" SIZE_T_FMT,
2062 idc, max_w, max_h );
2065 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2068 error_printf(
"could not size item!" );
2069 retval = MERROR_GUI;
2073 #define RETROGUI_CTL_TABLE_SZ( idx, c_name, c_fields ) \
2074 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2076 retval = retrogui_sz_ ## c_name( gui, ctl, p_w, p_h, max_w, max_h ); \
2077 maug_cleanup_if_not_ok();
2080 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_SZ )
2083#if RETROGUI_TRACE_LVL > 0
2084 debug_printf( RETROGUI_TRACE_LVL,
2085 "sized control " RETROGUI_IDC_FMT
" at " SIZE_T_FMT
"x" SIZE_T_FMT
"...",
2086 ctl->base.idc, ctl->base.w, ctl->base.h );
2097 struct RETROGUI* gui, RETROFLAT_IN_KEY* p_input,
2108 return RETROGUI_IDC_NONE;
2111 assert( !mdata_vector_is_locked( &((gui)->ctls) ) );
2114# if defined( RETROGUI_NATIVE_WIN )
2116 if( 0 == g_retroflat_state->last_idc ) {
2121 ctl = retrogui_get_ctl_by_idc( gui, g_retroflat_state->last_idc );
2122 g_retroflat_state->last_idc = 0;
2124#if RETROGUI_TRACE_LVL > 0
2125 debug_printf( RETROGUI_TRACE_LVL,
2126 "invalid IDC: " RETROGUI_IDC_FMT, gui->
focus );
2131# ifndef RETROGUI_NO_TEXTBOX
2132 if( RETROGUI_CTL_TYPE_TEXTBOX == ctl->base.type ) {
2133 if( SendMessage( ctl->base.hwnd, EM_GETMODIFY, 0, 0 ) ) {
2134 SendMessage( ctl->base.hwnd, EM_SETMODIFY, 0, 0 );
2135#if RETROGUI_TRACE_LVL > 0
2136 debug_printf( RETROGUI_TRACE_LVL,
"mod: %d",
2137 SendMessage( ctl->base.hwnd, EM_GETMODIFY, 0, 0 ) );
2147# define RETROGUI_CTL_TABLE_CLICK( idx, c_name, c_fields ) \
2148 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2149 gui->flags |= RETROGUI_FLAGS_DIRTY; \
2150 idc_out = retrogui_click_ ## c_name( gui, ctl, p_input, input_evt );
2152# define RETROGUI_CTL_TABLE_KEY( idx, c_name, c_fields ) \
2153 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2154 gui->flags |= RETROGUI_FLAGS_DIRTY; \
2155 idc_out = retrogui_key_ ## c_name( gui, ctl, p_input, input_evt );
2157 if( 0 != *p_input ) {
2158#if RETROGUI_TRACE_LVL > 0
2159 debug_printf( RETROGUI_TRACE_LVL,
2160 "focus " RETROGUI_IDC_FMT
" input: %d", gui->
focus, *p_input );
2165 if( retroflat_get_ms() < gui->debounce_next ) {
2166#if RETROGUI_TRACE_LVL > 0
2167 debug_printf( RETROGUI_TRACE_LVL,
2168 "debo! %d vs %d", retroflat_get_ms(), gui->debounce_next );
2173 if( 0 == *p_input ) {
2181 if( 0 <= gui->
focus ) {
2182 idc_out = gui->
focus;
2190 retrogui_focus_next( gui );
2192#if RETROGUI_TRACE_LVL > 0
2193 debug_printf( RETROGUI_TRACE_LVL,
"next: " RETROGUI_IDC_FMT, gui->
focus );
2202 retrogui_focus_prev( gui );
2204#if RETROGUI_TRACE_LVL > 0
2205 debug_printf( RETROGUI_TRACE_LVL,
"prev: " RETROGUI_IDC_FMT, gui->
focus );
2211# ifndef RETROGUI_NO_MOUSE
2213 RETROFLAT_MOUSE_B_LEFT == *p_input ||
2214 RETROFLAT_MOUSE_B_RIGHT == *p_input
2219#if RETROGUI_TRACE_LVL > 0
2220 debug_printf( RETROGUI_TRACE_LVL,
"resetting focus for mouse click..." );
2222 gui->
focus = RETROGUI_IDC_NONE;
2224 mouse_x = input_evt->
mouse_x - gui->x;
2225 mouse_y = input_evt->
mouse_y - gui->y;
2228 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
2230 mouse_x < ctl->base.x ||
2231 mouse_y < ctl->base.y ||
2232 mouse_x > ctl->base.x + ctl->base.w ||
2233 mouse_y > ctl->base.y + ctl->base.h
2238 if( gui->idc_prev == ctl->base.idc ) {
2241 idc_out = RETROGUI_IDC_NONE;
2245 gui->idc_prev = ctl->base.idc;
2247#if RETROGUI_TRACE_LVL > 0
2248 debug_printf( RETROGUI_TRACE_LVL,
2249 "setting focus to clicked control: " RETROGUI_IDC_FMT,
2252 gui->
focus = ctl->base.idc;
2255 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_CLICK )
2263 if( RETROGUI_IDC_NONE == gui->
focus ) {
2269 ctl = _retrogui_get_ctl_by_idc( gui, gui->
focus );
2274#if RETROGUI_TRACE_LVL > 0
2275 debug_printf( RETROGUI_TRACE_LVL,
2276 "invalid focus IDC: " RETROGUI_IDC_FMT, gui->
focus );
2282 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_KEY )
2287 gui->debounce_next = retroflat_get_ms() + gui->debounce_max;
2293 if( MERROR_OK != retval ) {
2294 idc_out = RETROGUI_IDC_NONE;
2320 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2326 RETROFLAT_COLOR_BLACK != gui->bg_color &&
2327 0 < gui->w && 0 < gui->h
2329 retroflat_2d_rect( gui->draw_bmp,
2333 #define RETROGUI_CTL_TABLE_REDRAW( idx, c_name, c_fields ) \
2334 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2336 gui->flags &= ~RETROGUI_FLAGS_DIRTY; \
2337 retrogui_redraw_ ## c_name( gui, ctl );
2340 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
2342 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_REDRAW )
2359 size_t x,
size_t y,
size_t w,
size_t h
2365 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2370#if RETROGUI_TRACE_LVL > 0
2371 debug_printf( RETROGUI_TRACE_LVL,
2372 "moving control " RETROGUI_IDC_FMT
" to: " SIZE_T_FMT
", " SIZE_T_FMT,
2376 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2379 error_printf(
"could not position control!" );
2380 retval = MERROR_GUI;
2384 #define RETROGUI_CTL_TABLE_POS( idx, c_name, c_fields ) \
2385 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2387 retval = retrogui_pos_ ## c_name( gui, ctl, x, y, w, h ); \
2388 maug_cleanup_if_not_ok();
2391 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_POS )
2394#if RETROGUI_TRACE_LVL > 0
2395 debug_printf( RETROGUI_TRACE_LVL,
2396 "moved control " RETROGUI_IDC_FMT
" to " SIZE_T_FMT
", " SIZE_T_FMT
2397 " and sized to " SIZE_T_FMT
"x" SIZE_T_FMT
"...",
2398 ctl->base.idc, gui->x + ctl->base.x, gui->y + ctl->base.y,
2399 ctl->base.w, ctl->base.h );
2423 assert( 0 < ctl->base.idc );
2425#ifdef RETROGXC_PRESENT
2426 if( 0 > gui->font_idx ) {
2428 if( (MAUG_MHANDLE)NULL == gui->
font_h ) {
2432 retval = MERROR_GUI;
2438#if RETROGUI_TRACE_LVL > 0
2439 debug_printf( RETROGUI_TRACE_LVL,
2444 RETROGUI_CTL_TYPE_IMAGE != ctl->base.type &&
2445 RETROFLAT_COLOR_NULL == ctl->base.bg_color
2448 "invalid background color specified for control " RETROGUI_IDC_FMT
"!",
2450 retval = MERROR_GUI;
2456 RETROGUI_CTL_TYPE_IMAGE != ctl->base.type &&
2457 RETROFLAT_COLOR_NULL == ctl->base.fg_color
2460 "invalid foreground color specified for control " RETROGUI_IDC_FMT
"!",
2462 retval = MERROR_GUI;
2468#ifdef RETROGUI_TRACE_TOKENS
2469 debug_printf( RETROGUI_TRACE_LVL,
2470 "pushing %s " RETROGUI_IDC_FMT
" to slot " SIZE_T_FMT
"...",
2471 gc_retrogui_ctl_names[ctl->base.type], ctl->base.idc,
2473#elif RETROGUI_TRACE_LVL > 0
2474 debug_printf( RETROGUI_TRACE_LVL,
2475 "pushing control type %d, " RETROGUI_IDC_FMT
" to slot " SIZE_T_FMT
"...",
2486 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2492 ctl = mdata_vector_get_last( &(gui->ctls),
2494 assert( NULL != ctl );
2496#if RETROGUI_TRACE_LVL > 0
2497# define RETROGUI_CTL_TABLE_PUSH( idx, c_name, c_fields ) \
2498 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2499 debug_printf( RETROGUI_TRACE_LVL, \
2500 "running " #c_name " push hook..." ); \
2501 retval = retrogui_push_ ## c_name( ctl ); \
2502 maug_cleanup_if_not_ok();
2504# define RETROGUI_CTL_TABLE_PUSH( idx, c_name, c_fields ) \
2505 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2506 retval = retrogui_push_ ## c_name( ctl ); \
2507 maug_cleanup_if_not_ok();
2511 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_PUSH )
2517 if( 0 == ctl->base.w || 0 == ctl->base.h ) {
2518#ifdef RETROGUI_TRACE_TOKENS
2519 debug_printf( RETROGUI_TRACE_LVL,
2520 "determining size for new %s control " RETROGUI_IDC_FMT
"...",
2521 gc_retrogui_ctl_names[ctl->base.type], ctl->base.idc );
2522#elif RETROGUI_TRACE_LVL > 0
2523 debug_printf( RETROGUI_TRACE_LVL,
2524 "determining size for new control type %d, " RETROGUI_IDC_FMT
"...",
2525 ctl->base.type, ctl->base.idc );
2527 retval = _retrogui_sz_ctl(
2528 gui, ctl->base.idc, &(ctl->base.w), &(ctl->base.h), 0, 0 );
2529 maug_cleanup_if_not_ok();
2533#if RETROGUI_TRACE_LVL > 0
2534 debug_printf( RETROGUI_TRACE_LVL,
2535 "setting focus to control: " RETROGUI_IDC_FMT, ctl->base.idc );
2537 gui->
focus = ctl->base.idc;
2556 if( mdata_vector_is_locked( &((gui)->ctls) ) ) {
2557 error_printf(
"GUI is locked!" );
2561 assert( !mdata_vector_is_locked( &((gui)->ctls) ) );
2564 #define RETROGUI_CTL_TABLE_FREE_CTL( idx, c_name, c_fields ) \
2565 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
2566 retrogui_destroy_ ## c_name( ctl );
2569 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
2570 if( idc != ctl->base.idc ) {
2576 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_FREE_CTL )
2596 struct RETROGUI* gui,
const char* font_path
2600#ifdef RETROGXC_PRESENT
2601 gui->font_idx = retrogxc_load_font( font_path, 0, 33, 93 );
2603 gui->font_idx, (ssize_t)0, SSIZE_T_FMT, MERROR_GUI );
2606 maug_cleanup_if_not_ok();
2616#ifndef RETROGUI_NO_TEXTBOX
2625 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2630 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2633 error_printf(
"could not get control text!" );
2634 retval = MERROR_GUI;
2638 if( RETROGUI_CTL_TYPE_TEXTBOX == ctl->base.type ) {
2639# if defined( RETROGUI_NATIVE_WIN )
2642 maug_mlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
2643 maug_cleanup_if_null_lock(
char*, ctl->TEXTBOX.text );
2645 maug_strncpy( buffer, ctl->TEXTBOX.text, buffer_sz );
2647 }
else if( RETROGUI_CTL_TYPE_LABEL == ctl->base.type ) {
2648# if defined( RETROGUI_NATIVE_WIN )
2651 maug_mlock( ctl->LABEL.label_h, ctl->LABEL.label );
2652 maug_cleanup_if_null_lock(
char*, ctl->LABEL.label );
2654 maug_strncpy( buffer, ctl->LABEL.label, buffer_sz );
2661 if( RETROGUI_CTL_TYPE_TEXTBOX == ctl->base.type ) {
2662 if( NULL != ctl->TEXTBOX.text ) {
2663 maug_munlock( ctl->TEXTBOX.text_h, ctl->TEXTBOX.text );
2666 }
else if( RETROGUI_CTL_TYPE_LABEL == ctl->base.type ) {
2667 if( NULL != ctl->LABEL.label ) {
2668 maug_munlock( ctl->LABEL.label_h, ctl->LABEL.label );
2689 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2694 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2697 error_printf(
"could not get control selection!" );
2698 retval = MERROR_GUI;
2702 assert( RETROGUI_CTL_TYPE_LISTBOX == ctl->base.type );
2704# if defined( RETROGUI_NATIVE_WIN )
2705 idx = SendMessage( ctl->base.hwnd, LB_GETCARETINDEX, 0, 0 );
2707 idx = ctl->LISTBOX.sel_idx;
2716 if( MERROR_OK != retval ) {
2732 assert( !mdata_vector_is_locked( &((gui)->ctls) ) );
2735#if RETROGUI_TRACE_LVL > 0
2736 debug_printf( RETROGUI_TRACE_LVL,
2737 "setting control " RETROGUI_IDC_FMT
" color %u to: %d",
2738 idc, color_key, color_val );
2742 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2745 error_printf(
"could not set control color!" );
2746 retval = MERROR_GUI;
2750 switch( color_key ) {
2757 error_printf(
"invalid color key specified: %u", color_key );
2772 const char* fmt, ...
2775 size_t label_sz = 0;
2776 char* label_tmp = NULL;
2777 char* buffer = NULL;
2779 MAUG_MHANDLE buffer_h = (MAUG_MHANDLE)NULL;
2782 assert( !mdata_vector_is_locked( &((gui)->ctls) ) );
2785#if RETROGUI_TRACE_LVL > 0
2786 debug_printf( RETROGUI_TRACE_LVL,
2787 "setting control " RETROGUI_IDC_FMT
" text to: %s", idc, fmt );
2791 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2794 error_printf(
"could not set control text!" );
2795 retval = MERROR_GUI;
2800 buffer_h = maug_malloc( 1, buffer_sz + 1 );
2801 maug_cleanup_if_null_alloc( MAUG_MHANDLE, buffer_h );
2803 assert( 0 < buffer_sz );
2805 maug_mlock( buffer_h, buffer );
2806 maug_cleanup_if_null_lock(
char*, buffer );
2807 maug_mzero( buffer, buffer_sz + 1 );
2809 assert( NULL != buffer );
2813 maug_mzero( buffer, buffer_sz + 1);
2817 va_start( args, fmt );
2818 maug_vsnprintf( buffer, buffer_sz, fmt, args );
2823 if( RETROGUI_CTL_TYPE_BUTTON == ctl->base.type ) {
2824 assert( NULL == ctl->BUTTON.label );
2825 _retrogui_copy_str( label, buffer, ctl->BUTTON, label_tmp, buffer_sz );
2826 }
else if( RETROGUI_CTL_TYPE_LABEL == ctl->base.type ) {
2827 assert( NULL == ctl->LABEL.label );
2828 _retrogui_copy_str( label, buffer, ctl->LABEL, label_tmp, label_sz );
2829#ifndef RETROGUI_NO_TEXTBOX
2830 }
else if( RETROGUI_CTL_TYPE_TEXTBOX == ctl->base.type ) {
2831 assert( NULL == ctl->TEXTBOX.text );
2833 label_sz = RETROGUI_CTL_TEXT_SZ_MAX;
2835 text, buffer, ctl->TEXTBOX, label_tmp, label_sz );
2836 ctl->TEXTBOX.text_cur = 0;
2839 error_printf(
"invalid control type! no label!" );
2848 if( NULL != buffer ) {
2849 maug_munlock( buffer_h, buffer );
2852 if( (MAUG_MHANDLE)NULL != buffer_h ) {
2853 maug_mfree( buffer_h );
2870 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2875#if RETROGUI_TRACE_LVL > 0
2876 debug_printf( RETROGUI_TRACE_LVL,
2877 "setting control " RETROGUI_IDC_FMT
" image to: %s", idc, path );
2881 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2884 error_printf(
"could not set control image!" );
2885 retval = MERROR_GUI;
2890 if( RETROGUI_CTL_TYPE_IMAGE == ctl->base.type ) {
2892# ifdef RETROGXC_PRESENT
2893 ctl->IMAGE.image_cache_id = -1;
2895 if( retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) ) ) {
2896 retroflat_2d_destroy_bitmap( &(ctl->IMAGE.image) );
2900 if( NULL != path ) {
2901# if defined( RETROGXC_PRESENT )
2902 ctl->IMAGE.image_cache_id = retrogxc_load_bitmap( path, flags );
2904 retroflat_2d_load_bitmap( path, &(ctl->IMAGE.image), flags );
2908 error_printf(
"invalid control type! no image!" );
2935 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
2940#if RETROGUI_TRACE_LVL > 0
2941 debug_printf( RETROGUI_TRACE_LVL,
2942 "setting control " RETROGUI_IDC_FMT
" image to: %p", idc, blit );
2946 ctl = _retrogui_get_ctl_by_idc( gui, idc );
2949 error_printf(
"could not set control image!" );
2950 retval = MERROR_GUI;
2955 if( RETROGUI_CTL_TYPE_IMAGE == ctl->base.type ) {
2956 if( NULL != blit ) {
2958# if defined( RETROGXC_PRESENT )
2959 ctl->IMAGE.image_cache_id = -1;
2962 ctl_img_w = retroflat_2d_bitmap_w( &(ctl->IMAGE.image) );
2963 ctl_img_h = retroflat_2d_bitmap_h( &(ctl->IMAGE.image) );
2964 blit_w = retroflat_2d_bitmap_w( blit );
2965 blit_h = retroflat_2d_bitmap_h( blit );
2969 retroflat_2d_bitmap_ok( &(ctl->IMAGE.image) ) &&
2970 (blit_w < ctl_img_w || blit_h < ctl_img_h)
2972 retroflat_2d_destroy_bitmap( &(ctl->IMAGE.image) );
2975#if RETROGUI_TRACE_LVL > 0
2976 debug_printf( RETROGUI_TRACE_LVL,
2977 "creating control " RETROGUI_IDC_FMT
" image: %u, %u",
2978 idc, blit_w, blit_h );
2982 retval = retroflat_2d_create_bitmap(
2983 blit_w, blit_h, &(ctl->IMAGE.image), 0 );
2984 maug_cleanup_if_not_ok();
2986 retroflat_2d_lock_bitmap( &(ctl->IMAGE.image) );
2988#if RETROGUI_TRACE_LVL > 0
2989 debug_printf( RETROGUI_TRACE_LVL,
2990 "blitting control " RETROGUI_IDC_FMT
" image from: %p", idc, blit );
2994 retroflat_2d_blit_bitmap(
2995 &(ctl->IMAGE.image),
2997 0, 0, 0, 0, blit_w, blit_h,
2998 ctl->IMAGE.instance );
2999 retroflat_2d_release_bitmap( &(ctl->IMAGE.image) );
3004 error_printf(
"invalid control type! no image!" );
3030 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
3035#if RETROGUI_TRACE_LVL > 0
3036 debug_printf( RETROGUI_TRACE_LVL,
3037 "setting control " RETROGUI_IDC_FMT
" level to: %u", idc, level );
3041 ctl = _retrogui_get_ctl_by_idc( gui, idc );
3044 error_printf(
"could not set control level!" );
3045 retval = MERROR_GUI;
3050 if( RETROGUI_CTL_TYPE_FILLBAR == ctl->base.type ) {
3051 ctl->FILLBAR.cur = level;
3053 ctl->FILLBAR.max = max;
3056 error_printf(
"invalid control type! no level!" );
3079#if RETROGUI_TRACE_LVL > 0
3080 debug_printf( RETROGUI_TRACE_LVL,
3081 "initializing control base " RETROGUI_IDC_FMT
"...", idc );
3086 ctl->base.type = type;
3087 ctl->base.idc = idc;
3088 ctl->base.fg_color = RETROFLAT_COLOR_NULL;
3089 ctl->base.bg_color = RETROFLAT_COLOR_NULL;
3090 ctl->base.sel_fg = RETROFLAT_COLOR_NULL;
3091 ctl->base.sel_bg = RETROFLAT_COLOR_NULL;
3093 #define RETROGUI_CTL_TABLE_INITS( idx, c_name, c_fields ) \
3094 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
3095 retrogui_init_ ## c_name( ctl );
3098 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_INITS )
3101# ifdef RETROGXC_PRESENT
3102 if( RETROGUI_CTL_TYPE_IMAGE == type ) {
3103 ctl->IMAGE.image_cache_id = -1;
3117 if( mdata_vector_is_locked( &((gui)->ctls) ) ) {
3118 error_printf(
"GUI is locked!" );
3126 assert( !mdata_vector_is_locked( &((gui)->ctls) ) );
3129 #define RETROGUI_CTL_TABLE_FREE( idx, c_name, c_fields ) \
3130 } else if( RETROGUI_CTL_TYPE_ ## c_name == ctl->base.type ) { \
3131 retrogui_destroy_ ## c_name( ctl );
3134 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
3136 RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_FREE )
3142# ifndef RETROGXC_PRESENT
3144 maug_mfree( gui->
font_h );
3150 mdata_vector_free( &(gui->ctls) );
3158 struct RETROGUI* gui,
size_t start, ssize_t incr
3164 ssize_t i_before = -1;
3171 if( !mdata_vector_is_locked( &((gui)->ctls) ) ) {
3180 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
3183 }
else if( RETROGUI_IDC_NONE == gui->
focus || 0 <= i_before ) {
3185 idc_out = ctl->base.idc;
3186#if RETROGUI_TRACE_LVL > 0
3187 debug_printf( RETROGUI_TRACE_LVL,
3188 "moving focus to control: " RETROGUI_IDC_FMT, idc_out );
3190 gui->
focus = idc_out;
3193 }
else if( ctl->base.idc == gui->
focus ) {
3206 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
3209#if RETROGUI_TRACE_LVL > 0
3211 RETROGUI_TRACE_LVL,
"skipping: " RETROGUI_IDC_FMT, i );
3215 idc_out = ctl->base.idc;
3216#if RETROGUI_TRACE_LVL > 0
3217 debug_printf( RETROGUI_TRACE_LVL,
3218 "moving focus to control: " RETROGUI_IDC_FMT, idc_out );
3220 gui->
focus = idc_out;
3228 ctl = mdata_vector_get( &(gui->ctls), i,
union RETROGUI_CTL );
3231#if RETROGUI_TRACE_LVL > 0
3233 RETROGUI_TRACE_LVL,
"skipping: " RETROGUI_IDC_FMT, i );
3237 idc_out = ctl->base.idc;
3238#if RETROGUI_TRACE_LVL > 0
3239 debug_printf( RETROGUI_TRACE_LVL,
3240 "moving focus to control: " RETROGUI_IDC_FMT, idc_out );
3242 gui->
focus = idc_out;
3248 error_printf(
"invalid focus: " RETROGUI_IDC_FMT, i );
3257 if( MERROR_OK != retval ) {
3258 idc_out = merror_retval_to_sz( retval );
3265#if RETROGUI_TRACE_LVL > 0
3267 RETROGUI_TRACE_LVL,
"selected IDC: " RETROGUI_IDC_FMT, idc_out );
3278 maug_mzero( gui,
sizeof(
struct RETROGUI ) );
3280 gui->bg_color = RETROFLAT_COLOR_BLACK;
3281 gui->
focus = RETROGUI_IDC_NONE;
3282 gui->debounce_max = RETROGUI_DEBOUNCE_MAX_DEFAULT;
3284#if RETROGUI_TRACE_LVL > 0
3285 debug_printf( RETROGUI_TRACE_LVL,
"initialized GUI" );
3293#define RETROGUI_CTL_TABLE_CONSTS( idx, c_name, c_fields ) \
3294 extern MAUG_CONST uint8_t SEG_MCONST RETROGUI_CTL_TYPE_ ## c_name;
3296RETROGUI_CTL_TABLE( RETROGUI_CTL_TABLE_CONSTS )
3298#ifdef RETROGUI_TRACE_TOKENS
3299extern MAUG_CONST
char* gc_retrogui_ctl_names[];
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:28
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition: retroflt.h:325
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:373
void retroflat_message(uint8_t flags, const char *title, const char *format,...)
Display a message in a dialog box and/or on stderr.
#define RETROFLAT_MSG_FLAG_ERROR
This icon/type flag indicates an error. It will try to display messages in an urgent way with a red i...
Definition: retroflt.h:461
size_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:870
#define RETROGUI_KEY_SEL_PREV
Overrideable constant defining the keyboard key (RETROFLAT_KEY_*) that will select the previous sub-i...
Definition: retrogui.h:147
#define RETROGUI_PAD_SEL_NEXT
Overrideable constant defining the gamepad button (RETROGUI_PAD_*) that will select the next sub-item...
Definition: retrogui.h:183
#define RETROGUI_KEY_NEXT
Overrideable constant defining the keyboard key (RETROFLAT_KEY_*) that will select the next activatea...
Definition: retrogui.h:120
#define RETROGUI_KEY_ACTIVATE
Overrideable constant defining the keyboard key (RETROFLAT_KEY_*) that will activate the RETROGUI_CTL...
Definition: retrogui.h:111
#define RETROGUI_PAD_ACTIVATE
Overrideable constant defining the gamepad button (RETROFLAT_PAD_*) that will activate the RETROGUI_C...
Definition: retrogui.h:156
#define RETROGUI_PAD_SEL_PREV
Overrideable constant defining the gamepad button (RETROGUI_PAD_*) that will select the previous sub-...
Definition: retrogui.h:192
#define RETROGUI_PAD_NEXT
Overrideable constant defining the gamepad button (RETROFLAT_PAD_*) that will select the next activat...
Definition: retrogui.h:165
#define RETROGUI_KEY_PREV
Overrideable constant defining the keyboard key (RETROFLAT_KEY_*) that will select the previous activ...
Definition: retrogui.h:129
#define RETROGUI_KEY_SEL_NEXT
Overrideable constant defining the keyboard key (RETROFLAT_KEY_*) that will select the next sub-item ...
Definition: retrogui.h:138
#define RETROGUI_PAD_PREV
Overrideable constant defining the gamepad button (RETROFLAT_PAD_*) that will select the previous act...
Definition: retrogui.h:174
#define RETROGUI_PADDING
Overrideable constant defining the padding for text inside of controls in pixels.
Definition: retrogui.h:207
#define RETROGUI_CTL_TABLE_FIELDS(idx, c_name, c_fields)
Creates the corresponding RETROGUI_* structs from ::RETROGUI_CTL_TABLE that populate union RETROGUI_C...
Definition: retrogui.h:397
#define retrogui_can_focus_ctl(ctl)
Determine if a RETROGUI_CTL can hold RETROGUI::focus.
Definition: retrogui.h:370
#define RETROGUI_CTL_TABLE_TYPES(idx, c_name, c_fields)
Adds the structs created by RETROGUI_CTL_TABLE_FIELDS to union RETROGUI_CTL.
Definition: retrogui.h:409
MERROR_RETVAL retrogui_set_ctl_level(struct RETROGUI *gui, retrogui_idc_t idc, uint16_t level, uint16_t max, uint8_t flags)
Set the current progress level displayed by a FILLBAR-type RETROGUI_CTL.
#define RETROGUI_COLOR_SEL_BG
Value for retrogui_set_ctl_color() color_key indicating selection background.
Definition: retrogui.h:312
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_remove_ctl(struct RETROGUI *gui, retrogui_idc_t idc)
Remove a control with the given unique identifier index from the given RETROGUI controller.
#define RETROGUI_COLOR_SEL_FG
Value for retrogui_set_ctl_color() color_key indicating selection foreground.
Definition: retrogui.h:318
#define RETROGUI_COLOR_BG
Value for retrogui_set_ctl_color() color_key indicating background.
Definition: retrogui.h:301
MERROR_RETVAL retrogui_destroy(struct RETROGUI *gui)
Free memory held by a RETROGUI controller internally and clean up any subordinate controls.
MERROR_RETVAL retrogui_set_ctl_image_blit(struct RETROGUI *gui, retrogui_idc_t idc, retroflat_blit_t *blit, uint8_t flags)
Blit the given image onto the control, ensuring that the size is sufficient to hold it.
retrogui_idc_t retrogui_focus_iter(struct RETROGUI *gui, size_t start, ssize_t incr)
Increment RETROGUI::focus, skipping elements that cannot hold focus.
MERROR_RETVAL retrogui_init(struct RETROGUI *gui)
Prepare a RETROGUI controller for use.
MERROR_RETVAL retrogui_set_font(struct RETROGUI *gui, const char *font_path)
Load the RetroFont API for the given RETROGUI to draw its controls with. Use RetroGXCache API if avai...
int16_t retrogui_idc_t
Unique identifying constant number for controls.
Definition: retrogui.h:292
#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:95
MERROR_RETVAL retrogui_set_ctl_image(struct RETROGUI *gui, retrogui_idc_t idc, const char *path, uint8_t flags)
Set the image displayed by an IMAGE-type RETROGUI_CTL.
#define RETROGUI_COLOR_FG
Value for retrogui_set_ctl_color() color_key indicating foreground.
Definition: retrogui.h:306
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.
void retrofont_string(retroflat_blit_t *target, RETROFLAT_COLOR color, const char *str, size_t str_sz, MAUG_MHANDLE font_h, size_t x, size_t y, size_t max_w, size_t max_h, uint8_t flags)
Draw a string with the given font.
#define RETROFONT_FLAG_SZ_MIN
Flag for retroflat_string_sz() to return the size of the shortest line in a multi-line string.
Definition: retrofnt.h:39
MERROR_RETVAL retrofont_load(const char *font_name, MAUG_MHANDLE *p_font_h, uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count)
Load a font for drawing.
A vector of uniformly-sized objects, stored contiguously.
Definition: mdata.h:93
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:320
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:353
size_t item_sz
Size, in bytes, of each item.
Definition: mdata.h:109
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:396
Fields common to ALL RETROGUI_CTL types.
Definition: retrogui.h:377
Definition: retrogui.h:430
#define RETROGUI_FLAGS_DIRTY
RETROGUI::flags indicating controls should be redrawn.
Definition: retrogui.h:248
MAUG_MHANDLE font_h
Font used to draw any attached RETROGUI_CTL.
Definition: retrogui.h:456
#define RETROGUI_FLAGS_FONT_OWNED
RETROGUI::flags indicating GUI font is owned by this RETROGUI and can/will be freed by retrogui_destr...
Definition: retrogui.h:255
retrogui_idc_t focus
Unique identifying index for current highlighted RETROGUI_CTL.
Definition: retrogui.h:440
Definition: retrogui.h:412