struct result app_ring_bell(struct app *app) { int code = cbreak(); if (ERR == code) return result_ncurses_err(); code = beep(); if (ERR == code) return result_ncurses_err(); code = raw(); if (ERR == code) return result_ncurses_err(); return result_success(); }
static struct result draw_window(struct selection *selection) { int result = wborder(selection->window, '|', '|', '-', '-', '+', '+', '+', '+'); if (OK != result) return result_ncurses_err(); // TODO: handle UTF-8 correctly size_t title_string_length = strlen(selection->title); if (title_string_length > (size_t)INT_MAX) { return result_set_system_error(ERANGE); } if (title_string_length) { int title_string_width = (int)title_string_length; int window_height; int window_width; getmaxyx(selection->window, window_height, window_width); char const left_frame[] = "- "; char const right_frame[] = " -"; int const left_frame_width = sizeof(left_frame) - 1; int const right_frame_width = sizeof(right_frame) - 1; int const left_border_width = 1; int const right_border_width = 1; int window_top_width = window_width - left_border_width - right_border_width; int title_width = left_frame_width + title_string_width + right_frame_width; if (window_top_width >= title_width) { int start = left_border_width + (window_top_width - title_width) / 2; result = mvwprintw(selection->window, 0, start, "%s%s%s", left_frame, selection->title, right_frame); if (ERR == result) return result_ncurses_err(); } else { // TODO: elide title } } result = wrefresh(selection->window); if (ERR == result) return result_ncurses_err(); return result_success(); }
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; }
static struct result get_selection(struct selection *selection) { while (true) { int ch = wgetch(selection->window); if (ERR == ch) return result_ncurses_err(); if (KEY_DOWN == ch) { int result = menu_driver(selection->menu, REQ_DOWN_ITEM); if (E_OK != result && E_REQUEST_DENIED != result) { return result_ncurses_error(result); } } if (KEY_UP == ch) { int result = menu_driver(selection->menu, REQ_UP_ITEM); if (E_OK != result && E_REQUEST_DENIED != result) { return result_ncurses_error(result); } } if ('\r' == ch) break; if (!isalnum(ch)) continue; for (int i = 0; i < selection->items_count; ++i) { char const *name = item_name(selection->items[i]); if (name && ch == name[0]) { set_current_item(selection->menu, selection->items[i]); return result_success(); } } } return result_success(); }
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(); }