X11 extended command selection

The expansion of the extended commands list to include every command
has made picking extended commands out of X11's menu become tedious.
This uses the existing 'extmenu' option (previously tty-only) to
control whether all the commands are present or just the traditional
subset not bound to non-meta keystrokes ('adjust', 'chat', 'loot', &c).
This commit is contained in:
PatR
2019-04-01 08:58:49 -07:00
parent cd12422af5
commit 0cad960428
5 changed files with 70 additions and 36 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winmisc.c $NHDT-Date: 1543830350 2018/12/03 09:45:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.42 $ */
/* NetHack 3.6 winmisc.c $NHDT-Date: 1554134316 2019/04/01 15:58:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.43 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -41,6 +41,8 @@
static Widget extended_command_popup = 0;
static Widget extended_command_form;
static Widget *extended_commands = 0;
static const char **command_list;
static short *command_indx;
static int extended_cmd_selected; /* index of the selected command; */
static int ps_selected; /* index of selected role */
#define PS_RANDOM (-50)
@@ -50,6 +52,7 @@ static const char ps_randchars[] = "*@\n\rrR";
static const char ps_quitchars[] = "\033qQ";
#define EC_NCHARS 32
static boolean ec_full_list = FALSE;
static boolean ec_active = FALSE;
static int ec_nchars = 0;
static char ec_chars[EC_NCHARS];
@@ -111,13 +114,14 @@ XtPointer
i2xtp(i)
int i;
{
return (XtPointer)(long)i;
return (XtPointer) (ptrdiff_t) i;
}
int
xtp2i(x)
XtPointer x;
{
return (long)x;
return (int) (ptrdiff_t) x;
}
/* Player Selection ------------------------------------------------------- */
@@ -1581,9 +1585,16 @@ X11_player_selection()
}
}
/* called by core to have the player pick an extended command */
int
X11_get_ext_cmd()
{
if (iflags.extmenu != ec_full_list) {
/* player has toggled the 'extmenu' option, toss the old widgets */
if (extended_commands)
release_extended_cmds(); /* will set extended_commands to Null */
ec_full_list = iflags.extmenu;
}
if (!extended_commands)
init_extended_commands_popup();
@@ -1597,15 +1608,19 @@ X11_get_ext_cmd()
/* The callbacks will enable the event loop exit. */
(void) x_event(EXIT_ON_EXIT);
return extended_cmd_selected;
if (extended_cmd_selected < 0)
return -1;
return command_indx[extended_cmd_selected];
}
void
release_extended_cmds()
{
if (extended_commands) {
XtDestroyWidget(extended_command_popup);
XtDestroyWidget(extended_command_popup), extended_command_popup = 0;
free((genericptr_t) extended_commands), extended_commands = 0;
free((genericptr_t) command_list), command_list = (const char **) 0;
free((genericptr_t) command_indx), command_indx = (short *) 0;
}
}
@@ -1816,6 +1831,22 @@ int ec_indx; /* might be greater than extended_cmd_selected */
}
}
/* decide whether extcmdlist[idx] should be part of extended commands menu */
static boolean
ignore_extcmd(idx)
int idx;
{
/* #shell or #suspect might not be available;
'extmenu' option controls whether we show full list
or just the traditional extended commands */
if ((extcmdlist[idx].flags & CMD_NOT_AVAILABLE) != 0
|| ((extcmdlist[idx].flags & AUTOCOMPLETE) == 0 && !ec_full_list)
|| strlen(extcmdlist[idx].ef_txt) < 2) /* ignore "#" and "?" */
return TRUE;
return FALSE;
}
/* ARGSUSED */
void
ec_key(w, event, params, num_params)
@@ -1886,19 +1917,14 @@ Cardinal *num_params;
if (extended_cmd_selected >= 0)
swap_fg_bg(extended_commands[extended_cmd_selected]);
extended_cmd_selected = -1; /* dismiss */
ec_chars[0] = ec_chars[ec_nchars-1];
ec_chars[0] = ec_chars[ec_nchars - 1];
ec_nchars = 1;
}
for (i = 0; extcmdlist[i].ef_txt; i++) {
if (extcmdlist[i].flags & CMD_NOT_AVAILABLE)
continue;
if (extcmdlist[i].ef_txt[0] == '?')
continue;
if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
for (i = 0; command_list[i]; ++i) {
if (!strncmp(ec_chars, command_list[i], ec_nchars)) {
if (extended_cmd_selected != i) {
/* I should use set() and unset() actions, but how do */
/* I send the an action to the widget? */
/* I should use set() and unset() actions, but how do
I send the an action to the widget? */
if (extended_cmd_selected >= 0)
swap_fg_bg(extended_commands[extended_cmd_selected]);
extended_cmd_selected = i;
@@ -1908,11 +1934,10 @@ Cardinal *num_params;
ambiguous choices, plus one to show thare aren't any
more such, will scroll into view */
do {
if (!extcmdlist[i + 1].ef_txt
|| *extcmdlist[i + 1].ef_txt == '?')
if (!command_list[i + 1])
break; /* end of list */
++i;
} while (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars));
} while (!strncmp(ec_chars, command_list[i], ec_nchars));
ec_scroll_to_view(i);
return;
@@ -1929,25 +1954,24 @@ static void
init_extended_commands_popup()
{
int i, j, num_commands, ignore_cmds = 0;
const char **command_list;
/* count commands */
for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++)
if (extcmdlist[num_commands].flags & CMD_NOT_AVAILABLE)
if (ignore_extcmd(num_commands))
++ignore_cmds;
/* If the last entry is "help", don't use it. */
if (strcmp(extcmdlist[num_commands - 1].ef_txt, "?") == 0)
--num_commands;
j = num_commands - ignore_cmds;
command_list = (const char **) alloc((unsigned) j * sizeof (char *));
command_list = (const char **) alloc((unsigned) (j * sizeof (char *) + 1));
command_indx = (short *) alloc((unsigned) (j * sizeof (short) + 1));
for (i = j = 0; i < num_commands; i++) {
if (extcmdlist[i].flags & CMD_NOT_AVAILABLE)
if (ignore_extcmd(i))
continue;
command_indx[j] = (short) i;
command_list[j++] = extcmdlist[i].ef_txt;
}
command_list[j] = (char *) 0;
command_indx[j] = -1;
num_commands = j;
extended_command_popup =
@@ -1955,8 +1979,6 @@ init_extended_commands_popup()
extended_command_translations, "dismiss", extend_dismiss,
"help", extend_help, num_commands, command_list,
&extended_commands, extend_select, &extended_command_form);
free((char *) command_list);
}
/* ------------------------------------------------------------------------ */