void menu_enter(void) { if (currentPointer->menu_function) currentPointer->menu_function(); if (currentPointer->child) { switch (menu_get_level(currentPointer)) { case 0: lcd_row_pos_level_1 = lcd_row_pos; break; case 1: lcd_row_pos_level_2 = lcd_row_pos; break; } // switch...case can be replaced by: // lcd_row_pos_level[ menu_get_level(currentPointer) ] = lcd_row_pos; menu_index = 0; lcd_row_pos = 0; currentPointer = currentPointer->child; menu_refresh(); } }
/* * Process these function after each TIMEOUT (default 3 seconds). * Order is important because some windows are on the top * of others. */ static void periodic(void) { check_wtmp(); update_load(); current->periodic(); wnoutrefresh(main_win); wnoutrefresh(info_win.wd); sub_periodic(); menu_refresh(); box_refresh(); info_refresh(); doupdate(); }
static void key_action(int key) { int i, size; if(signal_sent) { print_help(); signal_sent = 0; } /* * First, try to process the key by object (subwindow, menu) that * could be on top. */ size = sizeof key_funct/sizeof(int (*)(int)); for(i = 0; i < size; i++) if(key_funct[i](key)) goto SKIP; if(current->keys(key)) goto SKIP; /* cursor movement */ size = sizeof key_handlers/sizeof(struct key_handler); for(i = 0; i < size; i++) if(key_handlers[i].c == key) { key_handlers[i].handler(current); if(can_draw()) pad_draw(); goto SKIP; } switch(key) { case 'c': full_cmd ^= 1; current->redraw(); break; case '/': m_search(); break; case KBD_F1: help(); break; case KBD_ESC: case 'q': curses_end(); exit(0); default: return; } SKIP: dolog("%s: doing refresh\n", __FUNCTION__); wnoutrefresh(main_win); wnoutrefresh(info_win.wd); pad_refresh(); menu_refresh(); box_refresh(); info_refresh(); doupdate(); }
void menu_prev(void) { currentPointer = currentPointer->prev; if (menu_index) { menu_index--; if (lcd_row_pos > 0) lcd_row_pos--; } else { menu_index = menu_get_index(currentPointer); if (menu_index >= LCD_ROWS - 1) lcd_row_pos = LCD_ROWS - 1; else lcd_row_pos = menu_index; } menu_refresh(); }
void menu_back(void) { if (currentPointer->parent) { switch (menu_get_level(currentPointer)) { case 1: lcd_row_pos = lcd_row_pos_level_1; break; case 2: lcd_row_pos = lcd_row_pos_level_2; break; } currentPointer = currentPointer->parent; menu_index = menu_get_index(currentPointer); menu_refresh(); } }
void menu_next(void) { if (currentPointer->next) { currentPointer = (*currentPointer).next; menu_index++; if (++lcd_row_pos > LCD_ROWS - 1) lcd_row_pos = LCD_ROWS - 1; } else { menu_index = 0; lcd_row_pos = 0; if (currentPointer->parent) currentPointer = (currentPointer->parent)->child; else currentPointer = &menu1; } menu_refresh(); }
/* * Run multiple menus at the same time. * * If popup is true, the screen is saved before the menu is drawn, and * restored afterwards. Each time a popup menu is redrawn, it resets the * screen before redrawing. */ ui_event menu_select_multi(int *active, menu_type **menus, int num, int notify, bool popup) { ui_event in = EVENT_EMPTY; ui_event out = EVENT_EMPTY; bool no_act = FALSE; int i; assert(menus != NULL); assert(active != NULL); assert(num > 1); assert(*active < num); for (i = 0; i < num; i++) { assert(menus[i]->active.width != 0 && menus[i]->active.page_rows != 0); } notify |= (EVT_SELECT | EVT_ESCAPE); if (popup) { screen_save(); button_backup_all(TRUE); } /* Stop on first unhandled event */ //while (!(in.type & notify)) //while (!(in & notify)) while (!(in == EVT_SELECT) && !(in == EVT_ESCAPE)) { out = EVENT_EMPTY; if (popup) { button_restore(); screen_load(); screen_save(); button_backup_all(TRUE); } no_act = (menus[*active]->flags & MN_NO_ACTION) ? TRUE : FALSE; /* refresh all of the menus except the active one */ for (i = 0; i < num; i++) { if (i != *active) { menu_refresh(menus[i], FALSE); } } /* refresh the active menu */ menu_refresh(menus[*active], FALSE); //in = inkey_ex(); in = inkey_m(); /* Handle mouse & keyboard commands */ //if (in.type == EVT_MOUSE) { if (in & 0x80) { //if (!no_act && menu_handle_action(menu, &in)) { // continue; //} //menu_handle_mouse(menu, &in, &out); if (in == EVT_RESIZE) { /* resize all of the menus */ for (i = 0; i < num; i++) { menu_calc_size(menus[i]); if (menus[i]->row_funcs->resize) menus[i]->row_funcs->resize(menus[i]); } } else { int mx,my; char p; /* check which menu the click was in */ Term_peekmousepress(&p, &mx, &my); if (!rect_region_inside(&(menus[*active]->active), my, mx) ) { for (i = 0; i < num; i++) { if (rect_region_inside(&(menus[i]->active), my, mx)) { no_act = (menus[i]->flags & MN_NO_ACTION) ? TRUE : FALSE; *active = i; } } } /* handle the click in the active one */ if (!no_act && menu_handle_action(menus[*active], &in)) { continue; } menu_handle_mouse(menus[*active], &in, &out); } //} else if (in.type == EVT_KBRD) { } else { /* see if we need to move between menus */ /* handle the key press */ if (!no_act && menus[*active]->cmd_keys && //strchr(menu->cmd_keys, (char)in.key.code) && strchr(menus[*active]->cmd_keys, (char)in) && menu_handle_action(menus[*active], &in)) { continue; } menu_handle_keypress(menus[*active], &in, &out); }// else if (in.type == EVT_RESIZE) { // menu_calc_size(menu); // if (menu->row_funcs->resize) // menu->row_funcs->resize(menu); //} /* XXX should redraw menu here if cursor has moved */ /* if we requested it, send move events out */ if ((out == EVT_SELECT) && (menus[*active]->flags & MN_HANDLE_MOVE) && !no_act && menu_handle_action(menus[*active], &out)) continue; /* If we've selected an item, then send that event out */ //if (out.type == EVT_SELECT && !no_act && menu_handle_action(menu, &out)) if ((out == EVT_SELECT) && !no_act && menu_handle_action(menus[*active], &out)) continue; /* needed because EVT_* types are composed of multiple flags where in * angband they are one flag of an int, so the (notify & out) and * (!(in & notify)) is only true for particular EVT_* values */ /* Notify about the outgoing type */ //if (notify & out.type) { //if (notify & out) { if ((out == EVT_SELECT) || (out == EVT_ESCAPE)) { if (popup) { button_restore(); screen_load(); } return out; } } if (popup) { button_restore(); screen_load(); } return in; }
/* * Run a menu. * * If popup is true, the screen is saved before the menu is drawn, and * restored afterwards. Each time a popup menu is redrawn, it resets the * screen before redrawing. */ ui_event menu_select(menu_type *menu, int notify, bool popup) { ui_event in = EVENT_EMPTY; ui_event out = EVENT_EMPTY; bool no_act = (menu->flags & MN_NO_ACTION) ? TRUE : FALSE; assert(menu->active.width != 0 && menu->active.page_rows != 0); notify |= (EVT_SELECT | EVT_ESCAPE); if (popup) { screen_save(); button_backup_all(TRUE); } /* Stop on first unhandled event */ //while (!(in.type & notify)) //while (!(in & notify)) while (!(in == EVT_SELECT) && !(in == EVT_ESCAPE)) { out = EVENT_EMPTY; menu_refresh(menu, popup); //in = inkey_ex(); in = inkey_m(); /* Handle mouse & keyboard commands */ //if (in.type == EVT_MOUSE) { if (in & 0x80) { //if (!no_act && menu_handle_action(menu, &in)) { // continue; //} //menu_handle_mouse(menu, &in, &out); if (in == EVT_RESIZE) { menu_calc_size(menu); if (menu->row_funcs->resize) menu->row_funcs->resize(menu); } else { if (!no_act && menu_handle_action(menu, &in)) { continue; } menu_handle_mouse(menu, &in, &out); } //} else if (in.type == EVT_KBRD) { } else { if (!no_act && menu->cmd_keys && //strchr(menu->cmd_keys, (char)in.key.code) && strchr(menu->cmd_keys, (char)in) && menu_handle_action(menu, &in)) continue; menu_handle_keypress(menu, &in, &out); }// else if (in.type == EVT_RESIZE) { // menu_calc_size(menu); // if (menu->row_funcs->resize) // menu->row_funcs->resize(menu); //} /* XXX should redraw menu here if cursor has moved */ /* if we requested it, send move events out */ if ((out == EVT_SELECT) && (menu->flags & MN_HANDLE_MOVE) && !no_act && menu_handle_action(menu, &out)) continue; /* If we've selected an item, then send that event out */ //if (out.type == EVT_SELECT && !no_act && menu_handle_action(menu, &out)) if ((out == EVT_SELECT) && !no_act && menu_handle_action(menu, &out)) continue; /* needed because EVT_* types are composed of multiple flags where in * angband they are one flag of an int, so the (notify & out) and * (!(in & notify)) is only true for particular EVT_* values */ /* Notify about the outgoing type */ //if (notify & out.type) { //if (notify & out) { if ((out == EVT_SELECT) || (out == EVT_ESCAPE)) { if (popup) { button_restore(); screen_load(); } return out; } } if (popup) { button_restore(); screen_load(); } return in; }
/* * This is called when we receive a request for a command in the birth * process. * The birth process continues until we send a final character confirmation * command (or quit), so this is effectively called in a loop by the main * game. * * We're imposing a step-based system onto the main game here, so we need * to keep track of where we're up to, where each step moves on to, etc. */ errr get_birth_command(bool wait) { static enum birth_stage current_stage = BIRTH_RESET; static enum birth_stage prev; static enum birth_stage roller = BIRTH_RESET; enum birth_stage next = current_stage; switch (current_stage) { case BIRTH_RESET: { cmd_insert(CMD_BIRTH_RESET); roller = BIRTH_RESET; if (quickstart_allowed) next = BIRTH_QUICKSTART; else next = BIRTH_SEX_CHOICE; break; } case BIRTH_QUICKSTART: { display_player(0); next = get_quickstart_command(); break; } case BIRTH_SEX_CHOICE: case BIRTH_CLASS_CHOICE: case BIRTH_RACE_CHOICE: case BIRTH_ROLLER_CHOICE: { menu_type *menu = &sex_menu; cmd_code command = CMD_CHOOSE_SEX; Term_clear(); print_menu_instructions(); if (current_stage > BIRTH_SEX_CHOICE) { menu_refresh(&sex_menu, FALSE); menu = &race_menu; command = CMD_CHOOSE_RACE; } if (current_stage > BIRTH_RACE_CHOICE) { menu_refresh(&race_menu, FALSE); menu = &class_menu; command = CMD_CHOOSE_CLASS; } if (current_stage > BIRTH_CLASS_CHOICE) { menu_refresh(&class_menu, FALSE); menu = &roller_menu; command = CMD_NULL; } next = menu_question(current_stage, menu, command); if (next == BIRTH_BACK) next = current_stage - 1; /* Make sure that the character gets reset before quickstarting */ if (next == BIRTH_QUICKSTART) next = BIRTH_RESET; break; } case BIRTH_POINTBASED: { roller = BIRTH_POINTBASED; if (prev > BIRTH_POINTBASED) point_based_start(); next = point_based_command(); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; if (next != BIRTH_POINTBASED) point_based_stop(); break; } case BIRTH_ROLLER: { roller = BIRTH_ROLLER; next = roller_command(prev < BIRTH_ROLLER); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; break; } case BIRTH_NAME_CHOICE: { if (prev < BIRTH_NAME_CHOICE) display_player(0); next = get_name_command(); if (next == BIRTH_BACK) next = roller; break; } case BIRTH_FINAL_CONFIRM: { if (prev < BIRTH_FINAL_CONFIRM) display_player(0); next = get_confirm_command(); if (next == BIRTH_BACK) next = BIRTH_NAME_CHOICE; break; } default: { /* Remove dodgy compiler warning, */ } } prev = current_stage; current_stage = next; return 0; }
/* Allow the user to select from the current menu, and return the corresponding command to the game. Some actions are handled entirely by the UI (displaying help text, for instance). */ static enum birth_stage menu_question(enum birth_stage current, menu_type *current_menu, cmd_code choice_command) { struct birthmenu_data *menu_data = menu_priv(current_menu); ui_event cx; enum birth_stage next = BIRTH_RESET; /* Print the question currently being asked. */ clear_question(); Term_putstr(QUESTION_COL, QUESTION_ROW, -1, TERM_YELLOW, menu_data->hint); current_menu->cmd_keys = "?=*\x18"; /* ?, =, *, <ctl-X> */ while (next == BIRTH_RESET) { /* Display the menu, wait for a selection of some sort to be made. */ cx = menu_select(current_menu, EVT_KBRD, FALSE); /* As all the menus are displayed in "hierarchical" style, we allow use of "back" (left arrow key or equivalent) to step back in the proces as well as "escape". */ if (cx.type == EVT_ESCAPE) { next = BIRTH_BACK; } else if (cx.type == EVT_SELECT) { if (current == BIRTH_ROLLER_CHOICE) { cmd_insert(CMD_FINALIZE_OPTIONS); if (current_menu->cursor) { /* Do a first roll of the stats */ cmd_insert(CMD_ROLL_STATS); next = current + 2; } else { /* * Make sure we've got a point-based char to play with. * We call point_based_start here to make sure we get * an update on the points totals before trying to * display the screen. The call to CMD_RESET_STATS * forces a rebuying of the stats to give us up-to-date * totals. This is, it should go without saying, a hack. */ point_based_start(); cmd_insert(CMD_RESET_STATS); cmd_set_arg_choice(cmd_get_top(), 0, TRUE); next = current + 1; } } else { cmd_insert(choice_command); cmd_set_arg_choice(cmd_get_top(), 0, current_menu->cursor); next = current + 1; } } else if (cx.type == EVT_KBRD) { /* '*' chooses an option at random from those the game's provided. */ if (cx.key.code == '*' && menu_data->allow_random) { current_menu->cursor = randint0(current_menu->count); cmd_insert(choice_command); cmd_set_arg_choice(cmd_get_top(), 0, current_menu->cursor); menu_refresh(current_menu, FALSE); next = current + 1; } else if (cx.key.code == '=') { do_cmd_options_birth(); next = current; } else if (cx.key.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (cx.key.code == '?') { do_cmd_help(); } } } return next; }
/* * Interactive group by. * Recognises inscriptions, graphical symbols, lore */ static void display_knowledge(const char *title, int *obj_list, int o_count, group_funcs g_funcs, member_funcs o_funcs, const char *otherfields) { /* maximum number of groups to display */ int max_group = g_funcs.maxnum < o_count ? g_funcs.maxnum : o_count; /* This could (should?) be (void **) */ int *g_list, *g_offset; const char **g_names; int g_name_len = 8; /* group name length, minumum is 8 */ int grp_cnt = 0; /* total number groups */ int g_cur = 0, grp_old = -1; /* group list positions */ int o_cur = 0; /* object list positions */ int g_o_count = 0; /* object count for group */ int oid = -1; /* object identifiers */ region title_area = { 0, 0, 0, 4 }; region group_region = { 0, 6, MISSING, -2 }; region object_region = { MISSING, 6, 0, -2 }; /* display state variables */ bool tiles = (current_graphics_mode != NULL); bool tile_picker = FALSE; bool glyph_picker = FALSE; byte attr_top = 0; byte char_left = 0; int delay = 0; menu_type group_menu; menu_type object_menu; menu_iter object_iter = { NULL, NULL, display_group_member, NULL, NULL }; /* Panel state */ /* These are swapped in parallel whenever the actively browsing " */ /* changes */ int *active_cursor = &g_cur, *inactive_cursor = &o_cur; menu_type *active_menu = &group_menu, *inactive_menu = &object_menu; int panel = 0; void *swapspace; bool do_swap = FALSE; bool flag = FALSE; bool redraw = TRUE; int browser_rows; int wid, hgt; int i; int prev_g = -1; int omode = OPT(rogue_like_commands); ui_event ke; /* Get size */ Term_get_size(&wid, &hgt); browser_rows = hgt - 8; /* Disable the roguelike commands for the duration */ OPT(rogue_like_commands) = FALSE; /* Determine if using tiles or not */ if (tiles) tiles = (current_graphics_mode->grafID != 0); if (g_funcs.gcomp) sort(obj_list, o_count, sizeof(*obj_list), g_funcs.gcomp); /* Sort everything into group order */ g_list = C_ZNEW(max_group + 1, int); g_offset = C_ZNEW(max_group + 1, int); for (i = 0; i < o_count; i++) { if (prev_g != g_funcs.group(obj_list[i])) { prev_g = g_funcs.group(obj_list[i]); g_offset[grp_cnt] = i; g_list[grp_cnt++] = prev_g; } } g_offset[grp_cnt] = o_count; g_list[grp_cnt] = -1; /* The compact set of group names, in display order */ g_names = C_ZNEW(grp_cnt, const char *); for (i = 0; i < grp_cnt; i++) { int len; g_names[i] = g_funcs.name(g_list[i]); len = strlen(g_names[i]); if (len > g_name_len) g_name_len = len; } /* Reasonable max group name len */ if (g_name_len >= 20) g_name_len = 20; object_region.col = g_name_len + 3; group_region.width = g_name_len; /* Leave room for the group summary information */ if (g_funcs.summary) object_region.page_rows = -3; /* Set up the two menus */ menu_init(&group_menu, MN_SKIN_SCROLL, menu_find_iter(MN_ITER_STRINGS)); menu_setpriv(&group_menu, grp_cnt, g_names); menu_layout(&group_menu, &group_region); menu_init(&object_menu, MN_SKIN_SCROLL, &object_iter); menu_setpriv(&object_menu, 0, &o_funcs); menu_layout(&object_menu, &object_region); o_funcs.is_visual = FALSE; /* Save screen */ screen_save(); clear_from(0); /* This is the event loop for a multi-region panel */ /* Panels are -- text panels, two menus, and visual browser */ /* with "pop-up menu" for lore */ while ((!flag) && (grp_cnt)) { bool recall = FALSE; if (redraw) { /* Print the title bits */ region_erase(&title_area); prt(format("Knowledge - %s", title), 2, 0); prt("Group", 4, 0); prt("Name", 4, g_name_len + 3); if (otherfields) prt(otherfields, 4, 46); /* Print dividers: horizontal and vertical */ for (i = 0; i < 79; i++) Term_putch(i, 5, TERM_WHITE, '='); for (i = 0; i < browser_rows; i++) Term_putch(g_name_len + 1, 6 + i, TERM_WHITE, '|'); /* Reset redraw flag */ redraw = FALSE; } if (g_cur != grp_old) { grp_old = g_cur; o_cur = 0; g_o_count = g_offset[g_cur + 1] - g_offset[g_cur]; menu_set_filter(&object_menu, obj_list + g_offset[g_cur], g_o_count); group_menu.cursor = g_cur; object_menu.cursor = 0; } /* HACK ... */ if (!(tile_picker || glyph_picker)) { /* ... The object menu may be browsing the entire group... */ o_funcs.is_visual = FALSE; menu_set_filter(&object_menu, obj_list + g_offset[g_cur], g_o_count); object_menu.cursor = o_cur; } else { /* ... or just a single element in the group. */ o_funcs.is_visual = TRUE; menu_set_filter(&object_menu, obj_list + o_cur + g_offset[g_cur], 1); object_menu.cursor = 0; } oid = obj_list[g_offset[g_cur] + o_cur]; /* Print prompt */ { const char *pedit = (!o_funcs.xattr) ? "" : (!(attr_idx | char_idx) ? ", 'c' to copy" : ", 'c', 'p' to paste"); const char *xtra = o_funcs.xtra_prompt ? o_funcs.xtra_prompt(oid) : ""; const char *pvs = ""; if (tile_picker) pvs = ", ENTER to accept"; else if (glyph_picker) pvs = ", 'i' to insert, ENTER to accept"; else if (o_funcs.xattr) pvs = ", 'v' for visuals"; prt(format("<dir>%s%s%s, ESC", pvs, pedit, xtra), hgt - 1, 0); } if (do_swap) { do_swap = FALSE; swap(active_menu, inactive_menu); swap(active_cursor, inactive_cursor); panel = 1 - panel; } if (g_funcs.summary && !tile_picker && !glyph_picker) { g_funcs.summary(g_cur, obj_list, g_o_count, g_offset[g_cur], object_menu.active.row + object_menu.active.page_rows, object_region.col); } menu_refresh(inactive_menu, FALSE); menu_refresh(active_menu, FALSE); handle_stuff(p_ptr); if (tile_picker) { bigcurs = TRUE; display_tiles(g_name_len + 3, 7, browser_rows - 1, wid - (g_name_len + 3), attr_top, char_left); place_tile_cursor(g_name_len + 3, 7, *o_funcs.xattr(oid), (byte) * o_funcs.xchar(oid), attr_top, char_left); } if (glyph_picker) { display_glyphs(g_name_len + 3, 7, browser_rows - 1, wid - (g_name_len + 3), *o_funcs.xattr(oid), *o_funcs.xchar(oid)); } if (delay) { /* Force screen update */ Term_fresh(); /* Delay */ Term_xtra(TERM_XTRA_DELAY, delay); delay = 0; } ke = inkey_ex(); if (!tile_picker && !glyph_picker) { ui_event ke0 = EVENT_EMPTY; if (ke.type == EVT_MOUSE) menu_handle_mouse(active_menu, &ke, &ke0); else if (ke.type == EVT_KBRD) menu_handle_keypress(active_menu, &ke, &ke0); if (ke0.type != EVT_NONE) ke = ke0; } /* XXX Do visual mode command if needed */ if (o_funcs.xattr && o_funcs.xchar) { if (tiles) { if (tile_picker_command(ke, &tile_picker, browser_rows - 1, wid - (g_name_len + 3), &attr_top, &char_left, o_funcs.xattr(oid), (byte *) o_funcs.xchar(oid), g_name_len + 3, 7, &delay)) continue; } else { if (glyph_command(ke, &glyph_picker, browser_rows - 1, wid - (g_name_len + 3), o_funcs.xattr(oid), o_funcs.xchar(oid), g_name_len + 3, 7)) continue; } } switch (ke.type) { case EVT_KBRD: { if (ke.key.code == 'r' || ke.key.code == 'R') recall = TRUE; else if (o_funcs.xtra_act) o_funcs.xtra_act(ke.key, oid); break; } case EVT_MOUSE: { /* Change active panels */ if (region_inside(&inactive_menu->boundary, &ke)) { swap(active_menu, inactive_menu); swap(active_cursor, inactive_cursor); panel = 1 - panel; } continue; } case EVT_ESCAPE: { if (panel == 1) do_swap = TRUE; else flag = TRUE; break; } case EVT_SELECT: { if (panel == 0) do_swap = TRUE; else if (panel == 1 && oid >= 0 && o_cur == active_menu->cursor) recall = TRUE; break; } case EVT_MOVE: { *active_cursor = active_menu->cursor; break; } default: { break; } } /* Recall on screen */ if (recall) { if (oid >= 0) o_funcs.lore(oid); redraw = TRUE; } } /* Restore roguelike option */ OPT(rogue_like_commands) = omode; /* Prompt */ if (!grp_cnt) prt(format("No %s known.", title), 15, 0); FREE(g_names); FREE(g_offset); FREE(g_list); screen_load(); }
/* Allow the user to select from the current menu, and return the corresponding command to the game. Some actions are handled entirely by the UI (displaying help text, for instance). */ static enum birth_stage menu_question(enum birth_stage current, menu_type *current_menu, cmd_code choice_command) { struct birthmenu_data *menu_data = current_menu->menu_data; int cursor = current_menu->cursor; ui_event_data cx; enum birth_stage next = BIRTH_RESET; /* Print the question currently being asked. */ clear_question(); Term_putstr(QUESTION_COL, QUESTION_ROW, -1, TERM_YELLOW, menu_data->hint); current_menu->cmd_keys = "?=*\r\n\x18"; /* ?, ,= *, \n, <ctl-X> */ while (next == BIRTH_RESET) { button_kill_all(); button_add("[ENTER]", '\r'); if (menu_data->allow_random) button_add("[RANDOM]", '*'); button_add("[ESCAPE]", ESCAPE); button_add("[OPTIONS]", '='); button_add("[HELP]", '?'); button_add("[QUIT]", '\x18'); /* CTRL-X */ event_signal(EVENT_MOUSEBUTTONS); /* Display the menu, wait for a selection of some sort to be made. */ cx = menu_select(current_menu, &cursor, EVT_CMD); /* As all the menus are displayed in "hierarchical" style, we allow use of "back" (left arrow key or equivalent) to step back in the proces as well as "escape". */ if (cx.type == EVT_BACK || cx.type == EVT_ESCAPE || cx.key == ESCAPE) { next = BIRTH_BACK; } /* '\xff' or DEFINED_XFF is a mouse selection, '\r' a keyboard one. */ else if (cx.key == DEFINED_XFF || cx.key == '\r') { if (current == BIRTH_ROLLER_CHOICE) { if (cursor) { /* Do a first roll of the stats */ cmd_insert(CMD_ROLL_STATS); next = current + 2; } else { /* * Make sure we've got a point-based char to play with. * We call point_based_start here to make sure we get * an update on the points totals before trying to * display the screen. The call to CMD_RESET_STATS * forces a rebuying of the stats to give us up-to-date * totals. This is, it should go without saying, a hack. */ point_based_start(); cmd_insert(CMD_RESET_STATS, TRUE); next = current + 1; } } else { cmd_insert(choice_command, cursor); next = current + 1; } } /* '*' chooses an option at random from those the game's provided. */ else if (cx.key == '*' && menu_data->allow_random) { current_menu->cursor = randint0(current_menu->count); cmd_insert(choice_command, current_menu->cursor); menu_refresh(current_menu); next = current + 1; } else if (cx.key == '=') { do_cmd_options(); next = current; } else if (cx.key == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (cx.key == '?') { do_cmd_help(); } } return next; }
/** * Deal with events on the get_item menu */ bool get_item_action(menu_type *menu, const ui_event *event, int oid) { bool refresh = FALSE; struct object_menu_data *choice = menu_priv(menu); char key = event->key.code; int i, k; char *selections = (char *) menu->selections; if (event->type == EVT_SELECT) { selection = choice[oid].key; return FALSE; } if (event->type == EVT_KBRD) { if (key == '/') { /* Toggle to inventory */ if ((item_mode & USE_INVEN) && (p_ptr->command_wrk != USE_INVEN)) { p_ptr->command_wrk = USE_INVEN; build_obj_list(0, i2, NULL, olist_mode); refresh = TRUE; } /* Toggle to equipment */ else if ((item_mode & USE_EQUIP) && (p_ptr->command_wrk != USE_EQUIP)) { p_ptr->command_wrk = USE_EQUIP; build_obj_list(INVEN_WIELD, e2, NULL, olist_mode); refresh = TRUE; } /* No toggle allowed */ else { bell("Cannot switch item selector!"); } } else if (key == '-') { /* No toggle allowed */ if (f1 > f2) { bell("Cannot select floor!"); } /* Toggle to floor */ else { p_ptr->command_wrk = (USE_FLOOR); build_obj_list(0, f2, floor_list, olist_mode); refresh = TRUE; } } else if ((key >= '0') && (key <= '9')) { /* Look up the tag */ if (!get_tag(&k, key, item_cmd, item_mode & QUIVER_TAGS)) { bell("Illegal object choice (tag)!"); return TRUE; } /* Match the item */ for (i = 0; i < menu->count; i++) { if (choice[i].object == &p_ptr->inventory[k]) { Term_keypress(choice[i].key, 0); return TRUE; } } } if (refresh) { /* Load screen */ screen_load(); Term_fresh(); /* Save screen */ screen_save(); /* Show the prompt */ item_prompt(item_mode); menu_setpriv(menu, num_obj, items); for (i = 0; i < num_obj; i++) selections[i] = items[i].key; area.page_rows = menu->count + 1; menu_layout(menu, &area); menu_refresh(menu, TRUE); redraw_stuff(p_ptr); } return FALSE; } return TRUE; }
/** * This is called when we receive a request for a command in the birth * process. * The birth process continues until we send a final character confirmation * command (or quit), so this is effectively called in a loop by the main * game. * * We're imposing a step-based system onto the main game here, so we need * to keep track of where we're up to, where each step moves on to, etc. */ int textui_do_birth(void) { enum birth_stage current_stage = BIRTH_RESET; enum birth_stage prev; enum birth_stage roller = BIRTH_RESET; enum birth_stage next = current_stage; bool done = FALSE; cmdq_push(CMD_BIRTH_INIT); cmdq_execute(CMD_BIRTH); while (!done) { switch (current_stage) { case BIRTH_RESET: { cmdq_push(CMD_BIRTH_RESET); roller = BIRTH_RESET; if (quickstart_allowed) next = BIRTH_QUICKSTART; else next = BIRTH_RACE_CHOICE; break; } case BIRTH_QUICKSTART: { display_player(0); next = textui_birth_quickstart(); if (next == BIRTH_COMPLETE) done = TRUE; break; } case BIRTH_CLASS_CHOICE: case BIRTH_RACE_CHOICE: case BIRTH_ROLLER_CHOICE: { struct menu *menu = &race_menu; cmd_code command = CMD_CHOOSE_RACE; Term_clear(); print_menu_instructions(); if (current_stage > BIRTH_RACE_CHOICE) { menu_refresh(&race_menu, FALSE); menu = &class_menu; command = CMD_CHOOSE_CLASS; } if (current_stage > BIRTH_CLASS_CHOICE) { menu_refresh(&class_menu, FALSE); menu = &roller_menu; } next = menu_question(current_stage, menu, command); if (next == BIRTH_BACK) next = current_stage - 1; /* Make sure the character gets reset before quickstarting */ if (next == BIRTH_QUICKSTART) next = BIRTH_RESET; break; } case BIRTH_POINTBASED: { roller = BIRTH_POINTBASED; if (prev > BIRTH_POINTBASED) point_based_start(); next = point_based_command(); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; if (next != BIRTH_POINTBASED) point_based_stop(); break; } case BIRTH_ROLLER: { roller = BIRTH_ROLLER; next = roller_command(prev < BIRTH_ROLLER); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; break; } case BIRTH_NAME_CHOICE: { if (prev < BIRTH_NAME_CHOICE) display_player(0); next = get_name_command(); if (next == BIRTH_BACK) next = roller; break; } case BIRTH_HISTORY_CHOICE: { if (prev < BIRTH_HISTORY_CHOICE) display_player(0); next = get_history_command(); if (next == BIRTH_BACK) next = BIRTH_NAME_CHOICE; break; } case BIRTH_FINAL_CONFIRM: { if (prev < BIRTH_FINAL_CONFIRM) display_player(0); next = get_confirm_command(); if (next == BIRTH_BACK) next = BIRTH_HISTORY_CHOICE; if (next == BIRTH_COMPLETE) done = TRUE; break; } default: { /* Remove dodgy compiler warning, */ } } prev = current_stage; current_stage = next; /* Execute whatever commands have been sent */ cmdq_execute(CMD_BIRTH); } return 0; }