\#perminv, 2 of 2: implementation

Add new '|' command, aka #perminv, which allows the player to
send menu scrolling keystrokes to the persistent inventory window.

Implemented for X11, where its usefulness is limited, and for
curses, where it is more needed and also more fully functional.
The interface can either prompt for one keystroke, act upon it,
and return to normal play, or it can loop for multiple keystrokes
until player types <return> or <escape>.  X11 does the former if
the 'slow' application resource is False so that prompting uses
popups, and the latter when 'slow' is True where prompting is in
a fixed spot and doesn't end up causing the persistent inventory
window to be stacked behind the map window.  curses always does
the loop-until-done approach.  It also accepts up and down arrow
keys to scroll one line at a time.

Also adds two new menu scrolling commands, menu_shift_right (key
'}' by default) and menu_shift_left ('{') if wincap2 flags contain
WC2_MENU_SHIFT.  Shifting allows different substrings of too-long
lines to be seen.

For X11, neither works because their handling requires a horizontal
scrollbar and for some reason that escapes me our menus don't have
one of those.  If they did, shifts could work for all menus but a
shifted window would hide the selection letters.  So shifting would
be most usefully done as:  pan right, read more of any long lines,
immediately pan back to the left.

For curses, they only apply to the persistent inventory window.
Shift right redraws it with class headers and inventory letters
shown normally but the item descriptions omit their leftmost
portion, showing more text towards the end.  Shift left reverses
that and does nothing if the beginning is already in view.  Forward
and backward scrolling while shifted leave the shift in place.
This commit is contained in:
PatR
2021-03-13 18:18:53 -08:00
parent dd49431296
commit 946df19ea2
21 changed files with 784 additions and 110 deletions

View File

@@ -1885,6 +1885,8 @@ struct ext_func_tab extcmdlist[] = {
wiz_panic, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ 'p', "pay", "pay your shopping bill",
dopay, 0, NULL },
{ '|', "perminv", "scroll persistent inventory display",
doperminv, IFBURIED | GENERALCMD, NULL },
{ ',', "pickup", "pick up things at the current location",
dopickup, 0, NULL },
{ '\0', "polyself", "polymorph self",

View File

@@ -2291,6 +2291,55 @@ update_inventory(void)
(*windowprocs.win_update_inventory)(0);
}
/* '|' command - call interface's persistent inventory manipulation routine */
int
doperminv(void)
{
/*
* If persistent inventory window is enabled, interact with it.
*
* Depending on interface, might accept and execute one scrolling
* request (MENU_{FIRST,NEXT,PREVIOUS,LAST}_PAGE) then return,
* or might stay and handle multiple requests until user finishes
* (typically by typing <return> or <esc> but that's up to interface).
*/
if (iflags.debug_fuzzer)
return 0;
#if 0
/* [currently this would redraw the persistent inventory window
whether that's needed or not, so also reset any previous
scrolling; we don't want that if the interface only accepts
one scroll command at a time] */
update_inventory(); /* make sure that it's up to date */
#endif
if ((windowprocs.wincap & WC_PERM_INVENT) == 0) {
/* [TODO? perhaps omit "by <interface>" if all the window ports
compiled into this binary lack support for perm_invent...] */
pline("Persistent inventory display is not supported by '%s'.",
windowprocs.name);
} else if (!iflags.perm_invent) {
pline(
"Persistent inventory ('perm_invent' option) is not presently enabled.");
} else if (!g.invent) {
/* [should this be left for the interface to decide?] */
pline("Persistent inventory display is empty.");
} else {
/* note: we used to request a scrolling key here and pass that to
(*win_update_inventory)(key), but that limited the functionality
and also cluttered message history with prompt and response so
just send non-zero and have the interface be responsible for it */
(*windowprocs.win_update_inventory)(1);
} /* iflags.perm_invent */
return 0;
}
/* should of course only be called for things in invent */
static char
obj_to_let(struct obj *obj)

View File

@@ -224,6 +224,10 @@ static const menu_cmd_t default_menu_cmd_info[] = {
"Unselect all items on current page" },
{ "menu_search", MENU_SEARCH,
"Search and invert matching items" },
{ "menu_shift_right", MENU_SHIFT_RIGHT,
"Pan current page to right (perm_invent only)" },
{ "menu_shift_left", MENU_SHIFT_LEFT,
"Pan current page to left (perm_invent only)" },
{ (char *) 0, '\0', (char *) 0 }
};
@@ -1562,6 +1566,20 @@ optfn_menu_select_page(int optidx, int req, boolean negated,
return shared_menu_optfn(optidx, req, negated, opts, op);
}
static int
optfn_menu_shift_left(int optidx, int req, boolean negated,
char *opts, char *op)
{
return shared_menu_optfn(optidx, req, negated, opts, op);
}
static int
optfn_menu_shift_right(int optidx, int req, boolean negated,
char *opts, char *op)
{
return shared_menu_optfn(optidx, req, negated, opts, op);
}
/* end of shared key assignments for menu commands */
static int
@@ -6814,6 +6832,46 @@ map_menu_cmd(char ch)
return ch;
}
/* get keystrokes that are used for menu scrolling operations which apply;
printable: for use in a prompt, non-printable: for yn_function() choices */
char *
collect_menu_keys(
char *outbuf, /* at least big enough for 6 "M-^X" sequences +'\0'*/
unsigned scrollmask, /* 1: backwards, "^<"; 2: forwards, ">|";
* 4: left, "{"; 8: right, "}"; */
boolean printable) /* False: output is string of raw characters,
* True: output is a string of visctrl() sequences;
* matters iff user has mapped any menu scrolling
* commands to control or meta characters */
{
struct menuscrollinfo {
char cmdkey;
uchar maskindx;
};
static const struct menuscrollinfo scroll_keys[] = {
{ MENU_FIRST_PAGE, 1 },
{ MENU_PREVIOUS_PAGE, 1 },
{ MENU_NEXT_PAGE, 2 },
{ MENU_LAST_PAGE, 2 },
{ MENU_SHIFT_LEFT, 4 },
{ MENU_SHIFT_RIGHT, 8 },
};
int i;
outbuf[0] = '\0';
for (i = 0; i < SIZE(scroll_keys); ++i) {
if (scrollmask & scroll_keys[i].maskindx) {
char c = get_menu_cmd_key(scroll_keys[i].cmdkey);
if (printable)
Strcat(outbuf, visctrl(c));
else
(void) strkitten(outbuf, c);
}
}
return outbuf;
}
/* Returns the fid of the fruit type; if that type already exists, it
* returns the fid of that one; if it does not exist, it adds a new fruit
* type to the chain and returns the new one.
@@ -7381,6 +7439,7 @@ show_menu_controls(winid win, boolean dolist)
char buf[BUFSZ];
const char *fmt, *arg;
const struct xtra_cntrls *xcp;
boolean has_menu_shift = wc2_supported("menu_shift");
/*
* Relies on spaces to line things up in columns, so must be rendered
@@ -7390,11 +7449,16 @@ show_menu_controls(winid win, boolean dolist)
putstr(win, 0, "Menu control keys:");
if (dolist) { /* key bindings help: '?i' */
int i;
char ch;
fmt = "%-7s %s";
for (i = 0; default_menu_cmd_info[i].desc; i++) {
ch = default_menu_cmd_info[i].cmd;
if ((ch == MENU_SHIFT_RIGHT
|| ch == MENU_SHIFT_LEFT) && !has_menu_shift)
continue;
Sprintf(buf, fmt,
visctrl(get_menu_cmd_key(default_menu_cmd_info[i].cmd)),
visctrl(get_menu_cmd_key(ch)),
default_menu_cmd_info[i].desc);
putstr(win, 0, buf);
}
@@ -7436,6 +7500,16 @@ show_menu_controls(winid win, boolean dolist)
visctrl(get_menu_cmd_key(MENU_LAST_PAGE)),
"Last page");
putstr(win, 0, buf);
if (has_menu_shift) {
Sprintf(buf, mc_fmt, "Pan view",
visctrl(get_menu_cmd_key(MENU_SHIFT_RIGHT)),
"Right (perm_invent only)");
putstr(win, 0, buf);
Sprintf(buf, mc_fmt, "",
visctrl(get_menu_cmd_key(MENU_SHIFT_LEFT)),
"Left");
putstr(win, 0, buf);
}
putstr(win, 0, "");
Sprintf(buf, mc_fmt, "Search",
visctrl(get_menu_cmd_key(MENU_SEARCH)),
@@ -8090,6 +8164,7 @@ static struct wc_Opt wc2_options[] = {
{ "guicolor", WC2_GUICOLOR },
{ "hilite_status", WC2_HILITE_STATUS },
{ "hitpointbar", WC2_HITPOINTBAR },
{ "menu_shift", WC2_MENU_SHIFT },
{ "petattr", WC2_PETATTR },
{ "softkeyboard", WC2_SOFTKEYBOARD },
/* name shown in 'O' menu is different */