static void play_game(struct rnd *rnd) { struct game *game = game_alloc_or_die(rnd); struct result result = game_show(game); if (result_is_success(result)) result = game_run(game); game_hide(game); if (!result_is_success(result)) result_print_error(result); game_free_or_die(game); }
struct result app_activate_view(struct app *app, struct view *view) { struct result result = view_enable_keyboard(view); if (!result_is_success(result)) return result; app->active_view = view; return result_success(); }
struct result app_run(struct app *app) { sig_t previous_sigwinch_handler = signal(SIGWINCH, terminal_window_did_change); if (SIG_ERR == previous_sigwinch_handler) { return result_system_error(); } struct result result = result_success(); for (int i = 0; i < app->views_count; ++i) { result = app->views[i]->create(app->views[i], app); if (!result_is_success(result)) break; } if (result_is_success(result)) { for (int i = 0; i < app->views_count; ++i) { result = app->views[i]->draw(app->views[i], app); if (!result_is_success(result)) break; wnoutrefresh(app->views[i]->window); } } if (!app->active_view) { int i = app->views_count - 1; result = app_activate_view(app, app->views[i]); } doupdate(); if (result_is_success(result)) { result = dispatch_events(app); } for (int i = app->views_count - 1; i >= 0; --i) { app->views[i]->destroy(app->views[i], app); } signal(SIGWINCH, previous_sigwinch_handler); return result; }
static void run_tui(void) { struct app *app = app_alloc(); struct result result = app_run(app); if (!result_is_success(result)) { result_print_error(result); } app_free(app); }
static struct result dispatch_events(struct app *app) { struct result result = result_success(); app->is_running = true; do { int key = view_read_key(app->active_view); if (ERR == key) { result = result_ncurses_err(); app_quit(app); break; } result = app->active_view->on_key(app->active_view, app, key); if (!result_is_success(result)) { app_quit(app); break; } } while (app->is_running); return result; }
struct result selection_show(struct selection *selection, WINDOW *parent) { if (!selection) return result_set_system_error(EINVAL); selection->menu = new_menu(selection->items); if (!selection->menu) return result_ncurses_errno(); int menu_height; int menu_width; int code = scale_menu(selection->menu, &menu_height, &menu_width); if (E_OK != code) return result_ncurses_error(code); int title_width = (int)strlen(selection->title) + 1; if (title_width > menu_width) menu_width = title_width; int main_window_height; int main_window_width; getmaxyx(parent, main_window_height, main_window_width); int menu_window_height = menu_height + 4; int menu_window_width = menu_width + 5; int menu_window_y = (main_window_height - menu_window_height) / 2; int menu_window_x = (main_window_width - menu_window_width) / 2; selection->window = newwin(menu_window_height, menu_window_width, menu_window_y, menu_window_x); if (!selection->window) return result_ncurses_err(); code = keypad(selection->window, TRUE); if (ERR == code) return result_ncurses_err(); struct result result = draw_window(selection); if (!result_is_success(result)) return result; code = set_menu_win(selection->menu, selection->window); if (E_OK != code) return result_ncurses_error(code); int menu_sub_height = menu_height; int menu_sub_width = menu_width; int menu_sub_y = 2; int menu_sub_x = 2; selection->sub_window = derwin(selection->window, menu_sub_height, menu_sub_width, menu_sub_y, menu_sub_x); if (!selection->sub_window) return result_ncurses_err(); code = set_menu_sub(selection->menu, selection->sub_window); if (E_OK != code) return result_ncurses_error(code); selection->index = 0; code = post_menu(selection->menu); if (E_OK != code) return result_ncurses_error(code); code = wrefresh(selection->window); if (ERR == code) return result_ncurses_err(); result = get_selection(selection); if (!result_is_success(result)) return result; ITEM *selected_item = current_item(selection->menu); if (selected_item) selection->index = item_index(selected_item); code = unpost_menu(selection->menu); if (E_OK != code) return result_ncurses_error(code); code = wclear(selection->window); if (ERR == code) return result_ncurses_err(); code = wrefresh(selection->window); if (ERR == code) return result_ncurses_err(); code = free_menu(selection->menu); if (E_OK != code) return result_ncurses_error(code); selection->menu = NULL; code = delwin(selection->sub_window); if (E_OK != code) return result_ncurses_error(code); selection->sub_window = NULL; code = delwin(selection->window); if (E_OK != code) return result_ncurses_error(code); selection->window = NULL; return result_success(); }