/** * Display the options and redraw afterward. */ void do_cmd_xxx_options(void) { do_cmd_options(); do_cmd_redraw(); }
/* * Generic "get choice from menu" function */ static int get_player_choice(birth_menu *choices, int num, int def, int col, int wid, void (*hook)(birth_menu)) { int top = 0, next; int i, dir; char c; char buf[300]; bool done = FALSE; int hgt; byte attr; int cur = (def) ? def : 0; /* Autoselect if able */ //if (num == 1) done = TRUE; /* Clear */ for (i = TABLE_ROW; i < DESCRIPTION_ROW + 4; i++) { /* Clear */ Term_erase(col, i, Term->wid - wid); } /* Choose */ while (TRUE) { hgt = Term->hgt - TABLE_ROW - 1; /* Redraw the list */ for (i = 0; ((i + top < num) && (i <= hgt)); i++) { if (i + top < 26) { strnfmt(buf, sizeof(buf), "%c) %s", I2A(i + top), choices[i + top].name); } else { /* ToDo: Fix the ASCII dependency */ strnfmt(buf, sizeof(buf), "%c) %s", 'A' + (i + top - 26), choices[i + top].name); } /* Clear */ Term_erase(col, i + TABLE_ROW, wid); /* Display */ if (i == (cur - top)) { /* Highlight the current selection */ if (choices[i + top].ghost) attr = TERM_BLUE; else attr = TERM_L_BLUE; } else { if (choices[i + top].ghost) attr = TERM_SLATE; else attr = TERM_WHITE; } Term_putstr(col, i + TABLE_ROW, wid, attr, buf); } Term_erase(0, DESCRIPTION_ROW + 0, 255); Term_erase(0, DESCRIPTION_ROW + 1, 255); Term_erase(0, DESCRIPTION_ROW + 2, 255); Term_erase(0, DESCRIPTION_ROW + 3, 255); Term_erase(0, DESCRIPTION_ROW + 4, 255); if (choices[cur+top].text != NULL) { /* Indent output by 2 character, and wrap at column 70 */ text_out_wrap = 70; text_out_indent = 2; /* History */ Term_gotoxy(text_out_indent, DESCRIPTION_ROW); text_out_to_screen(TERM_L_WHITE, choices[cur+top].text); /* Reset text_out() vars */ text_out_wrap = 0; text_out_indent = 0; } else { /* Extra info */ // Term_putstr(QUESTION_COL, DESCRIPTION_ROW, -1, TERM_L_WHITE, // "Your sex has no gameplay effect."); } if (done) return (cur); /* Display auxiliary information if any is available. */ if (hook) hook(choices[cur]); /* Move the cursor */ put_str("", TABLE_ROW + cur - top, col); hide_cursor = TRUE; c = inkey(); hide_cursor = FALSE; /* Exit the game */ if ((c == 'Q') || (c == 'q')) quit(NULL); /* Hack - go back */ if ((c == ESCAPE)|| (c == '4')) return (INVALID_CHOICE); /* Make a choice */ if ((c == '\n') || (c == '\r') || (c == '6')) return (cur); /* Random choice */ if (c == '*') { /* Ensure legal choice */ do { cur = rand_int(num); } while (choices[cur].ghost); /* Done */ done = TRUE; } /* Alphabetic choice */ else if (isalpha(c)) { /* Options */ if ((c == 'O') || (c == 'o')) { do_cmd_options(); } else { int choice; if (islower(c)) choice = A2I(c); else choice = c - 'A' + 26; /* Validate input */ if ((choice > -1) && (choice < num) && !(choices[choice].ghost)) { cur = choice; /* Done */ done = TRUE; } else if (choices[choice].ghost) { bell("Your race cannot choose that house."); } else { bell("Illegal response to question!"); } } } /* Move */ else if (isdigit(c)) { /* Get a direction from the key */ dir = target_dir(c); /* Going up? */ if (dir == 8) { next = -1; for (i = 0; i < cur; i++) { if (!(choices[i].ghost)) { next = i; } } /* Move selection */ if (next != -1) cur = next; /* if (cur != 0) cur--; */ /* Scroll up */ if ((top > 0) && ((cur - top) < 4)) top--; } /* Going down? */ if (dir == 2) { next = -1; for (i = num - 1; i > cur; i--) { if (!(choices[i].ghost)) { next = i; } } /* Move selection */ if (next != -1) cur = next; /* if (cur != (num - 1)) cur++; */ /* Scroll down */ if ((top + hgt < (num - 1)) && ((top + hgt - cur) < 4)) top++; } } /* Invalid input */ else bell("Illegal response to question!"); /* If choice is off screen, move it to the top */ if ((cur < top) || (cur > top + hgt)) top = cur; } return (INVALID_CHOICE); }
/* * Generic "get choice from menu" function */ int get_player_choice(cptr *choices, int num, int col, int wid, cptr helpfile, void (*hook) (cptr)) { int top = 0, cur = 0; /* int bot = 13; */ int i, dir; char c; char buf[80]; bool done = FALSE; int hgt; /* Autoselect if able */ if (num == 1) done = TRUE; /* Clear */ for (i = TABLE_ROW; i < Term->hgt; i++) { /* Clear */ Term_erase(col, i, Term->wid - wid); } /* Choose */ while (TRUE) { /* * Note to Melkor: What happens when the screen is resized? * There is no 'redraw' hook at this point... * (That is why the original code restricted itself to what * would fit in the smallest possible screen.) -SF- */ hgt = Term->hgt - TABLE_ROW - 1; /* Redraw the list */ for (i = 0; ((i + top < num) && (i <= hgt)); i++) { if (i + top < 26) { strnfmt(buf, 80, "%c) %s", I2A(i + top), choices[i + top]); } else { /* ToDo: Fix the ASCII dependency */ strnfmt(buf, 80, "%c) %s", 'A' + (i + top - 26), choices[i + top]); } /* Clear */ Term_erase(col, i + TABLE_ROW, wid); /* Display */ if (i == (cur - top)) { /* Highlight the current selection */ put_fstr(col, i + TABLE_ROW, CLR_L_BLUE "%s", buf); } else { put_fstr(col, i + TABLE_ROW, buf); } } if (done) return (cur); /* Display auxiliary information if any is available. */ if (hook) hook(choices[cur]); /* Move the cursor */ Term_gotoxy(col, TABLE_ROW + cur - top); c = inkey(); if (c == KTRL('X')) { quit(NULL); } if (c == ESCAPE) { /* Mega Hack - go back. */ return (INVALID_CHOICE); } if (c == '*') { /* Select at random */ cur = randint0(num); /* Move it onto the screen */ if ((cur < top) || (cur > top + hgt)) { top = cur; } /* Done */ done = TRUE; } else if (c == '?') { (void)show_file(helpfile, NULL, 0, 0); } else if (c == '=') { do_cmd_options(OPT_FLAG_BIRTH | OPT_FLAG_SERVER | OPT_FLAG_PLAYER); } else if ((c == '\n') || (c == '\r')) { /* Done */ return (cur); } else if (isdigit(c)) { /* Get a direction from the key */ dir = get_keymap_dir(c); /* Going up? */ if (dir == 8) { if (cur != 0) { /* Move selection */ cur--; } if ((top > 0) && ((cur - top) < 4)) { /* Scroll up */ top--; } } /* Going down? */ if (dir == 2) { if (cur != (num - 1)) { /* Move selection */ cur++; } if ((top + hgt < (num - 1)) && ((top + hgt - cur) < 4)) { /* Scroll down */ top++; } } } else if (isalpha(c)) { int choice; if (islower(c)) { choice = A2I(c); } else { choice = c - 'A' + 26; } /* Validate input */ if ((choice > -1) && (choice < num)) { cur = choice; /* Move it onto the screen */ if ((cur < top) || (cur > top + hgt)) { top = cur; } /* Done */ done = TRUE; } else { /* Invalid input */ bell("Illegal birth choice!"); } } } return (INVALID_CHOICE); }
/* 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; }