doset_simple() revisited

For a compound option's value that uses getlin(), cancelling with
ESC wasn't dismissing the menu and could eventually result in a
"No window slots!" panic.  Clean up properly after ESC.

doset() and doset_simple() were sharing a format string but those
weren't the same if the longest option name differed.  Stop sharing.

doset_simple() didn't support menu_tab_sep.  Now it does.  (Tested
with Qt; really needs to be tested with WinGUI.  Enabling that is
expected to produce strange looking results with tty or curses.)
This commit is contained in:
PatR
2022-09-08 16:26:31 -07:00
parent a4c4e75467
commit 3ee6bcdf76

View File

@@ -299,7 +299,7 @@ static int count_menucolors(void);
static boolean parse_role_opts(int, boolean, const char *, char *, char **);
static unsigned int longest_option_name(int, int);
static int doset_simple_menu(void);
static void doset_add_menu(winid, const char *, int, int);
static void doset_add_menu(winid, const char *, const char *, int, int);
static int handle_add_list_remove(const char *, int);
static void all_options_menucolors(strbuf_t *);
static void all_options_msgtypes(strbuf_t *);
@@ -7757,11 +7757,7 @@ fruitadd(char *str, struct fruit *replace_fruit)
#define OPTIONS_HEADING "NETHACKOPTIONS"
#endif
/* [should be able to get away with not putting these in 'struct g'] */
static boolean made_doset_fmtstr = FALSE;
static char fmtstr_doset[] = "%s%-15s [%s] ";
static char fmtstr_doset_tab[] = "%s\t[%s]";
static char n_currently_set[] = "(%d currently set)";
static const char n_currently_set[] = "(%d currently set)";
DISABLE_WARNING_FORMAT_NONLITERAL /* RESTORE is after show_menucontrols() */
@@ -7967,15 +7963,28 @@ longest_option_name(int startpass, int endpass)
static int
doset_simple_menu(void)
{
/* unlike doset()'s fmtstr, there is no leading %s for indentation */
static const char fmtstr_tab_doset_simple[] = "%s\t[%s]";
char fmtstr_doset_simple[sizeof "%-15s [%s] "];
menu_item *pick_list;
boolean *bool_p;
const char *name;
const char *name, *fmtstr;
char buf[BUFSZ], buf2[BUFSZ], abuf[BUFSZ];
winid tmpwin;
anything any;
enum OptSection section;
int i, k, pick_cnt, reslt;
/* we do this each time we're called instead of once in doset_simple()
in case 'menu_tab_sep' ever gets included in the simple menu so
becomes subject to being changed while doset_simple() is running */
if (!iflags.menu_tab_sep)
Sprintf(fmtstr_doset_simple, "%%-%us [%%s]",
longest_option_name(set_gameview, set_in_game));
else
Strcpy(fmtstr_doset_simple, fmtstr_tab_doset_simple);
fmtstr = fmtstr_doset_simple;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
@@ -8003,8 +8012,7 @@ doset_simple_menu(void)
continue;
if (iflags.wc_tiled_map && allopt[i].idx == opt_color)
continue;
Sprintf(buf, fmtstr_doset, "",
name, *bool_p ? "X" : " ");
Sprintf(buf, fmtstr, name, *bool_p ? "X" : " ");
break;
case CompOpt:
case OthrOpt:
@@ -8021,7 +8029,7 @@ doset_simple_menu(void)
if (allopt[k].optfn)
reslt = (*allopt[k].optfn)(allopt[k].idx, get_val,
FALSE, buf2, empty_optstr);
Sprintf(buf, fmtstr_doset, "", name,
Sprintf(buf, fmtstr, name,
((reslt == optn_ok && buf2[0])
? (const char *) buf2 : "unknown"));
break;
@@ -8048,6 +8056,7 @@ doset_simple_menu(void)
if (pick_cnt > 0) {
k = pick_list[0].item.a_int - 1;
abuf[0] = '\0';
if (allopt[k].opttyp == BoolOpt) {
/* boolean option */
Sprintf(buf, "%s%s", *allopt[k].addr ? "!" : "", allopt[k].name);
@@ -8066,19 +8075,21 @@ doset_simple_menu(void)
got_from_config[k] = TRUE;
} else {
Sprintf(buf, "Set %s to what?", allopt[k].name);
abuf[0] = '\0'; /* suppress EDIT_GETLIN */
getlin(buf, abuf);
if (abuf[0] == '\033')
return -1;
Sprintf(buf, "%s:", allopt[k].name);
copynchars(eos(buf), abuf,
(int) (sizeof buf - 1 - strlen(buf)));
/* pass the buck */
(void) parseoptions(buf, FALSE, FALSE);
if (abuf[0] != '\033') { /* ESC */
Sprintf(buf, "%s:", allopt[k].name);
copynchars(eos(buf), abuf,
(int) (sizeof buf - 1 - strlen(buf)));
/* pass the buck */
(void) parseoptions(buf, FALSE, FALSE);
}
/* Note: using ESC to not set a new value will still return
'picked 1' to caller which will loop for another choice */
}
}
if (wc_supported(allopt[k].name) || wc2_supported(allopt[k].name))
if (abuf[0] != '\033'
&& (wc_supported(allopt[k].name)
|| wc2_supported(allopt[k].name)))
preference_update(allopt[k].name);
free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
@@ -8119,11 +8130,6 @@ doset_simple(void)
return doset();
}
if (!made_doset_fmtstr) {
Sprintf(fmtstr_doset, "%%s%%-%us [%%s]",
longest_option_name(set_gameview, set_in_game));
made_doset_fmtstr = TRUE;
}
give_opt_msg = FALSE;
do {
pickedone = doset_simple_menu();
@@ -8136,8 +8142,10 @@ doset_simple(void)
int
doset(void) /* changing options via menu by Per Liboriussen */
{
static const char fmtstr_tab_doset[] = "%s%s\t[%s]";
char fmtstr_doset[sizeof "%s%-15s [%s] "];
char buf[BUFSZ];
const char *name;
const char *name, *indent;
int i = 0, pass, pick_cnt, pick_idx, opt_indx;
boolean *bool_p;
winid tmpwin;
@@ -8197,11 +8205,12 @@ doset(void) /* changing options via menu by Per Liboriussen */
startpass = set_gameview;
endpass = (wizard) ? set_wiznofuz : set_in_game;
if (!made_doset_fmtstr && !iflags.menu_tab_sep) {
if (!iflags.menu_tab_sep)
/* initial "%s" is for indentation of non-selectable items */
Sprintf(fmtstr_doset, "%%s%%-%us [%%s]",
longest_option_name(startpass, endpass));
made_doset_fmtstr = TRUE;
}
else
Strcpy(fmtstr_doset, fmtstr_tab_doset);
indexoffset = 1;
any = cg.zeroany;
@@ -8227,12 +8236,9 @@ doset(void) /* changing options via menu by Per Liboriussen */
continue;
any.a_int = (pass == 0) ? 0 : i + 1 + indexoffset;
if (!iflags.menu_tab_sep)
Sprintf(buf, fmtstr_doset, (pass == 0) ? " " : "",
name, *bool_p ? "true" : "false");
else
Sprintf(buf, fmtstr_doset_tab,
name, *bool_p ? "true" : "false");
indent = (pass == 0 && !iflags.menu_tab_sep) ? " " : "";
Sprintf(buf, fmtstr_doset, indent,
name, *bool_p ? "true" : "false");
if (pass == 0)
enhance_menu_text(buf, sizeof buf, pass, bool_p,
&allopt[i]);
@@ -8247,12 +8253,12 @@ doset(void) /* changing options via menu by Per Liboriussen */
MENU_ITEMFLAGS_NONE);
/* deliberately put playmode, name, role+race+gender+align first */
doset_add_menu(tmpwin, "playmode", opt_playmode, 0);
doset_add_menu(tmpwin, "name", opt_name, 0);
doset_add_menu(tmpwin, "role", opt_role, 0);
doset_add_menu(tmpwin, "race", opt_race, 0);
doset_add_menu(tmpwin, "gender", opt_gender, 0);
doset_add_menu(tmpwin, "align", opt_align, 0);
doset_add_menu(tmpwin, "playmode", fmtstr_doset, opt_playmode, 0);
doset_add_menu(tmpwin, "name", fmtstr_doset, opt_name, 0);
doset_add_menu(tmpwin, "role", fmtstr_doset, opt_role, 0);
doset_add_menu(tmpwin, "race", fmtstr_doset, opt_race, 0);
doset_add_menu(tmpwin, "gender", fmtstr_doset, opt_gender, 0);
doset_add_menu(tmpwin, "align", fmtstr_doset, opt_align, 0);
for (pass = startpass; pass <= endpass; pass++)
for (i = 0; (name = allopt[i].name) != 0; i++) {
@@ -8267,7 +8273,7 @@ doset(void) /* changing options via menu by Per Liboriussen */
|| (is_wc2_option(name) && !wc2_supported(name)))
continue;
doset_add_menu(tmpwin, name, i,
doset_add_menu(tmpwin, name, fmtstr_doset, i,
(pass == set_gameview) ? 0 : indexoffset);
}
}
@@ -8288,7 +8294,7 @@ doset(void) /* changing options via menu by Per Liboriussen */
|| (is_wc2_option(name) && !wc2_supported(name)))
continue;
doset_add_menu(tmpwin, name, i,
doset_add_menu(tmpwin, name, fmtstr_doset, i,
(pass == set_gameview) ? 0 : indexoffset);
}
}
@@ -8301,7 +8307,7 @@ doset(void) /* changing options via menu by Per Liboriussen */
iflags.menu_headings, clr,
"Variable playground locations:", MENU_ITEMFLAGS_NONE);
for (i = 0; i < PREFIX_COUNT; i++)
doset_add_menu(tmpwin, fqn_prefix_names[i], -1, 0);
doset_add_menu(tmpwin, fqn_prefix_names[i], fmtstr_doset, -1, 0);
#endif
end_menu(tmpwin, "Set what options?");
g.opt_need_redraw = FALSE;
@@ -8387,11 +8393,13 @@ static void
doset_add_menu(
winid win, /* window to add to */
const char *option, /* option name */
const char *fmtstr, /* fmtstr_doset */
int idx, /* index in allopt[] */
int indexoffset) /* value to add to index in allopt[],
* or zero if option cannot be changed */
{
const char *value = "unknown"; /* current value */
const char *indent;
char buf[BUFSZ], buf2[BUFSZ];
anything any;
int i = idx, reslt = optn_err;
@@ -8425,11 +8433,8 @@ doset_add_menu(
}
/* " " replaces "a - " -- assumes menus follow that style */
if (!iflags.menu_tab_sep)
Sprintf(buf, fmtstr_doset, any.a_int ? "" : " ", option,
value);
else
Sprintf(buf, fmtstr_doset_tab, option, value);
indent = !any.a_int ? " " : "";
Sprintf(buf, fmtstr, indent, option, value);
add_menu(win, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE);
}