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