From fd43f38d2a28cf4ceba220b067718e8833822d93 Mon Sep 17 00:00:00 2001 From: winyf Date: Sun, 31 May 2026 01:51:17 -0400 Subject: [PATCH] implement very bad resizing support --- src/main.c | 274 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 154 insertions(+), 120 deletions(-) diff --git a/src/main.c b/src/main.c index 43fc6eb..5f6a550 100644 --- a/src/main.c +++ b/src/main.c @@ -13,22 +13,25 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include #include #include #include #include -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#define STR(s) #s +#define XSTR(s) STR(s) +#define MIN_ROWS 24 +#define MIN_COLS 80 +#define ERR_TERM_TOO_SMALL "This program requires a terminal that is at least " XSTR(MIN_COLS) "x" XSTR(MIN_ROWS) + #define mvwclrtobot(win, y, x) (wmove((win), (y), (x)) == ERR ? ERR : wclrtobot((win))) -#define NUM_FIELDS 7 -void draw_output(WINDOW* win, int race, int sex, int spec, int sign, int attrs[ATTRIBUTE_COUNT], int skills[SKILL_COUNT]); +void draw_output(WINDOW* win, int race, int sex, int spec, int sign, const int attrs[ATTRIBUTE_COUNT], const int skills[SKILL_COUNT]); enum FIELDS { - RACE, SEX, SPEC, ATTR, SKILL_MAJ, SKILL_MIN, SIGN + RACE, SEX, SPEC, ATTR, SKILL_MAJ, SKILL_MIN, SIGN, FIELD_COUNT }; typedef struct mw_menu { MENU *m; @@ -44,6 +47,11 @@ int main() { WINDOW *win_input, *win_output; PANEL *panel_input, *panel_output; initscr(); + if (LINES < MIN_ROWS || COLS < MIN_COLS) { + endwin(); + fprintf(stderr, "%s\n", ERR_TERM_TOO_SMALL); + return 1; + } cbreak(); noecho(); keypad(stdscr, 1); @@ -61,19 +69,20 @@ int main() { int out_skills[SKILL_COUNT] = {0}; int out_attrs[ATTRIBUTE_COUNT] = {0}; - int input_col_width = (COLS - 2) / 5; + int input_col_width = (MIN_COLS - 2) / 5; + int input_col_spacing = (COLS - 2) / 5; int input_col_height = 6; - WINDOW *field_windows[NUM_FIELDS]; + WINDOW *field_windows[FIELD_COUNT]; field_windows[0] = newwin(input_col_height/2, input_col_width, 1, 1 ); field_windows[1] = newwin(input_col_height/2, input_col_width, input_col_height/2+1, 1 ); - field_windows[2] = newwin(input_col_height/2, input_col_width, 1, input_col_width+1); - field_windows[3] = newwin(input_col_height/2, input_col_width, input_col_height/2+1, input_col_width+1); - field_windows[4] = newwin(input_col_height, input_col_width, 1, input_col_width*2+1); - field_windows[5] = newwin(input_col_height, input_col_width, 1, input_col_width*3+1); - field_windows[6] = newwin(input_col_height, input_col_width, 1, input_col_width*4+1); + field_windows[2] = newwin(input_col_height/2, input_col_width, 1, input_col_spacing+1); + field_windows[3] = newwin(input_col_height/2, input_col_width, input_col_height/2+1, input_col_spacing+1); + field_windows[4] = newwin(input_col_height, input_col_width, 1, input_col_spacing*2+1); + field_windows[5] = newwin(input_col_height, input_col_width, 1, input_col_spacing*3+1); + field_windows[6] = newwin(input_col_height, input_col_width, 1, input_col_spacing*4+1); - PANEL *field_panels[NUM_FIELDS]; - for (int i = 0; i < NUM_FIELDS; ++i) { + PANEL *field_panels[FIELD_COUNT]; + for (int i = 0; i < FIELD_COUNT; ++i) { field_panels[i] = new_panel(field_windows[i]); } const char *field_headers[] = { @@ -127,8 +136,8 @@ int main() { wattroff(w, A_BOLD); } mvwchgat(field_windows[selected_field], 0, 0, -1, A_BOLD | A_REVERSE, 0, NULL); - mw_menu field_menus[NUM_FIELDS] = {0}; - for (int i = 0; i < NUM_FIELDS; ++i) { + mw_menu field_menus[FIELD_COUNT] = {0}; + for (int i = 0; i < FIELD_COUNT; ++i) { int x, y; field_menus[i].num_selections = 0; field_menus[i].max_selections = field_max_selections[i]; @@ -187,115 +196,142 @@ int main() { ITEM **cur_menu_items; int *other_menu_selected; while ((ch = getch()) != KEY_F(1)) { - if (in_field_menu == -1) { - switch(ch) { - case KEY_LEFT: - selected_col = (selected_col + 4) % 5; - selection_changed = 1; - break; - case KEY_RIGHT: - selected_col = (selected_col + 1) % 5; - selection_changed = 1; - break; - case KEY_UP: - case KEY_DOWN: - selected_row = !selected_row; - selection_changed = 1; - break; - case ' ': - if (selected_field == SEX) { - field_menus[SEX].selections[0] = !field_menus[SEX].selections[0]; - mvwclrtobot(selected_field_window, 1, 0); - waddstr(selected_field_window, field_strings[SEX][field_menus[SEX].selections[0]]); - menu_updated = 1; - break; - } - - cur_menu = &field_menus[selected_field]; - other_menu_selected = NULL; - if (selected_field == SKILL_MAJ) { - other_menu_selected = field_menus[SKILL_MIN].selections; - } else if (selected_field == SKILL_MIN) { - other_menu_selected = field_menus[SKILL_MAJ].selections; - } - cur_menu_items = menu_items(cur_menu->m); - if (other_menu_selected != NULL) { - for (int i = 0; i < field_items[selected_field]; ++i) { - item_opts_on(cur_menu_items[i], O_SELECTABLE); - } - for (int i = 0; i < cur_menu->max_selections && other_menu_selected[i] != -1; ++i) { - item_opts_off(cur_menu_items[other_menu_selected[i]], O_SELECTABLE); - } - } - show_panel(cur_menu->p); - in_field_menu = selected_field; - break; - } - if (selection_changed) { - mvwchgat(selected_field_window, 0, 0, -1, A_BOLD, 0, NULL); - if (selected_col < 2) { - selected_field = selected_col * 2 + selected_row; - } else { - selected_field = selected_col + 2; - } - selected_field_window = field_windows[selected_field]; - mvwchgat(selected_field_window, 0, 0, -1, A_BOLD | A_REVERSE, 0, NULL); - selection_changed = 0; + if (ch == KEY_RESIZE) { + if (LINES < MIN_ROWS || COLS < MIN_COLS) { + endwin(); + fprintf(stderr, "%s\n", ERR_TERM_TOO_SMALL); + return 1; + } + werase(win_input); + box(win_input, 0, 0); + int old_spacing = input_col_spacing; + input_col_spacing = (COLS - 2) / 5; + if (input_col_spacing != old_spacing) { + move_panel(field_panels[1], input_col_height/2+1, 1 ); + move_panel(field_panels[2], 1, input_col_spacing+1); + move_panel(field_panels[3], input_col_height/2+1, input_col_spacing+1); + move_panel(field_panels[4], 1, input_col_spacing*2+1); + move_panel(field_panels[5], 1, input_col_spacing*3+1); + move_panel(field_panels[6], 1, input_col_spacing*4+1); + menu_updated = 1; + } + for (int i = 0; i < FIELD_COUNT; ++i) { + if (!field_menus[i].p) continue; + int x, y; + getmaxyx(field_menus[i].w, y, x); + move_panel(field_menus[i].p, (LINES-y)/2, (COLS-x)/2); } } else { - switch(ch) { - case KEY_UP: - menu_driver(cur_menu->m, REQ_UP_ITEM); - break; - case KEY_DOWN: - menu_driver(cur_menu->m, REQ_DOWN_ITEM); - break; - case KEY_LEFT: - menu_driver(cur_menu->m, REQ_LEFT_ITEM); - break; - case KEY_RIGHT: - menu_driver(cur_menu->m, REQ_RIGHT_ITEM); - break; - case ' ': - if(cur_menu->max_selections > 1) { - ITEM* cur_item = current_item(cur_menu->m); - if (item_opts(cur_item) & O_SELECTABLE) { - menu_driver(cur_menu->m, REQ_TOGGLE_ITEM); - if (item_value(cur_item)) { - if(cur_menu->num_selections == cur_menu->max_selections) { - menu_driver(cur_menu->m, REQ_TOGGLE_ITEM); - } else { - cur_menu->num_selections += 1; - } - } else { - cur_menu->num_selections -= 1; + if (in_field_menu == -1) { + switch(ch) { + case KEY_LEFT: + selected_col = (selected_col + 4) % 5; + selection_changed = 1; + break; + case KEY_RIGHT: + selected_col = (selected_col + 1) % 5; + selection_changed = 1; + break; + case KEY_UP: + case KEY_DOWN: + selected_row = !selected_row; + selection_changed = 1; + break; + case ' ': + if (selected_field == SEX) { + field_menus[SEX].selections[0] = !field_menus[SEX].selections[0]; + mvwclrtobot(selected_field_window, 1, 0); + waddstr(selected_field_window, field_strings[SEX][field_menus[SEX].selections[0]]); + menu_updated = 1; + break; + } + + cur_menu = &field_menus[selected_field]; + other_menu_selected = NULL; + if (selected_field == SKILL_MAJ) { + other_menu_selected = field_menus[SKILL_MIN].selections; + } else if (selected_field == SKILL_MIN) { + other_menu_selected = field_menus[SKILL_MAJ].selections; + } + cur_menu_items = menu_items(cur_menu->m); + if (other_menu_selected != NULL) { + for (int i = 0; i < field_items[selected_field]; ++i) { + item_opts_on(cur_menu_items[i], O_SELECTABLE); + } + for (int i = 0; i < cur_menu->max_selections && other_menu_selected[i] != -1; ++i) { + item_opts_off(cur_menu_items[other_menu_selected[i]], O_SELECTABLE); } } + show_panel(cur_menu->p); + in_field_menu = selected_field; break; } - case '\n': - if (cur_menu->max_selections > 1) { - for (int i = 0, j = 0; i < field_items[selected_field]; ++i){ - if(item_value(cur_menu_items[i])) { - cur_menu->selections[j++] = i; - } - } - for (int j = cur_menu->num_selections; j < cur_menu->max_selections; ++j) { - cur_menu->selections[j] = -1; - } + if (selection_changed) { + mvwchgat(selected_field_window, 0, 0, -1, A_BOLD, 0, NULL); + if (selected_col < 2) { + selected_field = selected_col * 2 + selected_row; } else { - cur_menu->selections[0] = item_index(current_item(cur_menu->m)); - } - mvwclrtobot(selected_field_window, 1, 0); - - for (int i = 0; i < cur_menu->num_selections; ++i) { - mvwaddstr(selected_field_window, i+1, 0, field_strings[selected_field][cur_menu->selections[i]]); + selected_field = selected_col + 2; } + selected_field_window = field_windows[selected_field]; + mvwchgat(selected_field_window, 0, 0, -1, A_BOLD | A_REVERSE, 0, NULL); + selection_changed = 0; + } + } else { + switch(ch) { + case KEY_UP: + menu_driver(cur_menu->m, REQ_UP_ITEM); + break; + case KEY_DOWN: + menu_driver(cur_menu->m, REQ_DOWN_ITEM); + break; + case KEY_LEFT: + menu_driver(cur_menu->m, REQ_LEFT_ITEM); + break; + case KEY_RIGHT: + menu_driver(cur_menu->m, REQ_RIGHT_ITEM); + break; + case ' ': + if(cur_menu->max_selections > 1) { + ITEM* cur_item = current_item(cur_menu->m); + if (item_opts(cur_item) & O_SELECTABLE) { + menu_driver(cur_menu->m, REQ_TOGGLE_ITEM); + if (item_value(cur_item)) { + if(cur_menu->num_selections == cur_menu->max_selections) { + menu_driver(cur_menu->m, REQ_TOGGLE_ITEM); + } else { + cur_menu->num_selections += 1; + } + } else { + cur_menu->num_selections -= 1; + } + } + break; + } + case '\n': + if (cur_menu->max_selections > 1) { + for (int i = 0, j = 0; i < field_items[selected_field]; ++i){ + if(item_value(cur_menu_items[i])) { + cur_menu->selections[j++] = i; + } + } + for (int j = cur_menu->num_selections; j < cur_menu->max_selections; ++j) { + cur_menu->selections[j] = -1; + } + } else { + cur_menu->selections[0] = item_index(current_item(cur_menu->m)); + } + mvwclrtobot(selected_field_window, 1, 0); + + for (int i = 0; i < cur_menu->num_selections; ++i) { + mvwaddstr(selected_field_window, i+1, 0, field_strings[selected_field][cur_menu->selections[i]]); + } - hide_panel(cur_menu->p); - menu_updated = 1; - in_field_menu = -1; - break; + hide_panel(cur_menu->p); + menu_updated = 1; + in_field_menu = -1; + break; + } } } if (menu_updated) { @@ -324,7 +360,7 @@ int main() { return 0; } -void draw_output(WINDOW* win, int race, int sex, int spec, int sign, int attrs[ATTRIBUTE_COUNT], int skills[SKILL_COUNT]) { +void draw_output(WINDOW* win, int race, int sex, int spec, int sign, const int attrs[ATTRIBUTE_COUNT], const int skills[SKILL_COUNT]) { int y, x; getmaxyx(win, y, x); int col_width = x / 5; @@ -472,6 +508,4 @@ void draw_output(WINDOW* win, int race, int sex, int spec, int sign, int attrs[A mvwprintw(win, row, col, "%-12s%3d", MW_SKILL_STR[i], final_skills[i]); } - - } \ No newline at end of file