pull request #897 - setting 'autounlock' option

Pull request from entrez:  simply the 'O' submenu for autounlock by
removing choice 'none'.  Fix error reporting for bad autounlock value
from run-time config file or NETHACKOPTIONS.

Fixes #897
This commit is contained in:
PatR
2022-10-12 17:03:11 -07:00
+24 -33
View File
@@ -193,7 +193,6 @@ static NEARDATA const char *msgwind[][3] = { /* 'msg_window' settings */
#endif #endif
/* autounlock settings */ /* autounlock settings */
static NEARDATA const char *unlocktypes[][2] = { static NEARDATA const char *unlocktypes[][2] = {
{ "none", "" },
{ "untrap", "(might fail)" }, { "untrap", "(might fail)" },
{ "apply-key", "" }, { "apply-key", "" },
{ "kick", "(doors only)" }, { "kick", "(doors only)" },
@@ -776,18 +775,22 @@ optfn_autounlock(
newflags = 0; newflags = 0;
sep = index(op, '+') ? '+' : ' '; sep = index(op, '+') ? '+' : ' ';
while (op) { while (op) {
boolean matched = FALSE;
op = trimspaces(op); /* might have leading space */ op = trimspaces(op); /* might have leading space */
if ((nxt = index(op, sep)) != 0) { if ((nxt = index(op, sep)) != 0) {
*nxt++ = '\0'; *nxt++ = '\0';
op = trimspaces(op); /* might have trailing space after op = trimspaces(op); /* might have trailing space after
* plus sign removal */ * plus sign removal */
} }
for (i = 0; i < SIZE(unlocktypes); ++i) if (str_start_is("none", op, TRUE))
if (!strncmpi(op, unlocktypes[i][0], Strlen(op)) negated = TRUE, matched = TRUE;
for (i = 0; i < SIZE(unlocktypes) && !matched; ++i) {
if (str_start_is(unlocktypes[i][0], op, TRUE)
/* fuzzymatch() doesn't match leading substrings but /* fuzzymatch() doesn't match leading substrings but
this allows "apply_key" and "applykey" to match this allows "apply_key" and "applykey" to match
"apply-key"; "apply key" too if part of foo+bar */ "apply-key"; "apply key" too if part of foo+bar */
|| fuzzymatch(op, unlocktypes[i][0], " -_", TRUE)) { || fuzzymatch(op, unlocktypes[i][0], " -_", TRUE)) {
matched = TRUE;
switch (*op) { switch (*op) {
case 'n': case 'n':
negated = TRUE; negated = TRUE;
@@ -805,11 +808,16 @@ optfn_autounlock(
newflags |= AUTOUNLOCK_FORCE; newflags |= AUTOUNLOCK_FORCE;
break; break;
default: default:
config_error_add("Invalid value for \"%s\": \"%s\"", matched = FALSE;
allopt[optidx].name, op); break;
return optn_silenterr;
} }
} }
}
if (!matched) {
config_error_add("Invalid value for \"%s\": \"%s\"",
allopt[optidx].name, op);
return optn_silenterr;
}
op = nxt; op = nxt;
} }
if (negated && newflags != 0) { if (negated && newflags != 0) {
@@ -832,13 +840,13 @@ optfn_autounlock(
*opts = '\0'; *opts = '\0';
if (flags.autounlock & AUTOUNLOCK_UNTRAP) if (flags.autounlock & AUTOUNLOCK_UNTRAP)
Sprintf(eos(opts), "%s%s", p, unlocktypes[1][0]), p = plus; Sprintf(eos(opts), "%s%s", p, unlocktypes[0][0]), p = plus;
if (flags.autounlock & AUTOUNLOCK_APPLY_KEY) if (flags.autounlock & AUTOUNLOCK_APPLY_KEY)
Sprintf(eos(opts), "%s%s", p, unlocktypes[2][0]), p = plus; Sprintf(eos(opts), "%s%s", p, unlocktypes[1][0]), p = plus;
if (flags.autounlock & AUTOUNLOCK_KICK) if (flags.autounlock & AUTOUNLOCK_KICK)
Sprintf(eos(opts), "%s%s", p, unlocktypes[3][0]), p = plus; Sprintf(eos(opts), "%s%s", p, unlocktypes[2][0]), p = plus;
if (flags.autounlock & AUTOUNLOCK_FORCE) if (flags.autounlock & AUTOUNLOCK_FORCE)
Sprintf(eos(opts), "%s%s", p, unlocktypes[4][0]); /*no more p*/ Sprintf(eos(opts), "%s%s", p, unlocktypes[3][0]); /*no more p*/
} }
return optn_ok; return optn_ok;
} }
@@ -4856,38 +4864,21 @@ handler_autounlock(int optidx)
for (i = 0; i < SIZE(unlocktypes); ++i) { for (i = 0; i < SIZE(unlocktypes); ++i) {
Sprintf(buf, "%-10.10s%c%.40s", Sprintf(buf, "%-10.10s%c%.40s",
unlocktypes[i][0], sep, unlocktypes[i][1]); unlocktypes[i][0], sep, unlocktypes[i][1]);
presel = !i ? !flags.autounlock : (flags.autounlock & (1 << (i - 1))); presel = (flags.autounlock & (1 << i));
any.a_int = i + 1; any.a_int = i + 1;
add_menu(tmpwin, &nul_glyphinfo, &any, *unlocktypes[i][0], 0, add_menu(tmpwin, &nul_glyphinfo, &any, *unlocktypes[i][0], 0,
ATR_NONE, clr, buf, ATR_NONE, clr, buf,
((presel ? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE) (presel ? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE));
| (!i ? MENU_ITEMFLAGS_SKIPINVERT : 0)));
} }
Sprintf(buf, "Select '%.20s' actions:", optname); Sprintf(buf, "Select '%.20s' actions:", optname);
end_menu(tmpwin, buf); end_menu(tmpwin, buf);
n = select_menu(tmpwin, PICK_ANY, &window_pick); n = select_menu(tmpwin, PICK_ANY, &window_pick);
if (n > 0) { if (n > 0) {
int k; unsigned newflags = 0;
boolean wasnone = !flags.autounlock;
unsigned newflags = 0, noflags = 0;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i)
k = window_pick[i].item.a_int - 1; newflags |= (1 << (window_pick[i].item.a_int - 1));
if (k) flags.autounlock = newflags;
newflags |= (1 << (k - 1));
else
noflags = 1;
}
/* wasnone: 'none' is preselected;
!wasnone: don't force it to be unselected */
if (newflags && noflags && !wasnone) {
config_error_add(
"Invalid value combination for \"%s\": 'none' with some",
optname);
res = optn_silenterr;
} else {
flags.autounlock = newflags;
}
free((genericptr_t) window_pick); free((genericptr_t) window_pick);
} else if (n == 0) { /* nothing was picked but menu wasn't cancelled */ } else if (n == 0) { /* nothing was picked but menu wasn't cancelled */
/* something that was preselected got unselected, leaving nothing; /* something that was preselected got unselected, leaving nothing;