From fc52f0ef42b30437bcd3e826c810a8adce174ee2 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 14 Nov 2023 21:33:09 -0800 Subject: [PATCH] 'menu_headings' option If the value is "no color&none" report it as "no-color&none" in 'm O' and for #saveoptions. Allow "OPTIONS=menu_headings" without any color or attribute value to mean "no-color&inverse" as it once did before the player could choose which attribute or color was supported, and matching the default used when 'menu_headings' hasn't been specified at all. Accept "OPTIONS=!menu_headings", meaning "no-color&none". Explicitly reject "OPTIONS=!menu_headings:anything". It was rejecting that due to blanket rejection of negated option, but reporting "can't both have a value and be negated" whether there was any value present or not. For preselected menu entries when interactively choosing a new value via the submenu of 'm O', use the current color and attribute rather than NO_COLOR and ATR_NONE. --- include/extern.h | 4 +-- include/optlist.h | 2 +- src/botl.c | 4 +-- src/options.c | 68 ++++++++++++++++++++++++++++------------------- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/include/extern.h b/include/extern.h index 59a4c39f9..aeeacb26a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2086,8 +2086,8 @@ extern int add_autopickup_exception(const char *); extern void free_autopickup_exceptions(void); extern void set_playmode(void); extern int sym_val(const char *); -extern int query_color(const char *); -extern int query_attr(const char *); +extern int query_color(const char *, int); +extern int query_attr(const char *, int); extern boolean query_color_attr(color_attr *, const char *); extern const char *clr2colorname(int); extern int match_str2clr(char *); diff --git a/include/optlist.h b/include/optlist.h index cbbc545c0..8e7d911f9 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -399,7 +399,7 @@ static int optfn_##a(int, int, boolean, char *, char *); NHOPTC(menu_first_page, Advanced, 4, opt_in, set_in_config, No, Yes, No, No, NoAlias, "jump to the first page in a menu") NHOPTC(menu_headings, Advanced, 4, opt_in, set_in_game, - No, Yes, No, Yes, NoAlias, "display style for menu headings") + Yes, Yes, No, Yes, NoAlias, "display style for menu headings") NHOPTC(menu_invert_all, Advanced, 4, opt_in, set_in_config, No, Yes, No, No, NoAlias, "invert all items in a menu") NHOPTC(menu_invert_page, Advanced, 4, opt_in, set_in_config, diff --git a/src/botl.c b/src/botl.c index 68ead6db3..04b69a24a 100644 --- a/src/botl.c +++ b/src/botl.c @@ -3911,14 +3911,14 @@ status_hilite_menu_add(int origfld) } choose_color: - clr = query_color(colorqry); + clr = query_color(colorqry, NO_COLOR); if (clr == -1) { if (behavior != BL_TH_ALWAYS_HILITE) goto choose_value; else goto choose_behavior; } - atr = query_attr(attrqry); + atr = query_attr(attrqry, ATR_NONE); if (atr == -1) goto choose_color; diff --git a/src/options.c b/src/options.c index 9a7f92e17..5c91f631f 100644 --- a/src/options.c +++ b/src/options.c @@ -2037,7 +2037,8 @@ color_attr_parse_str(color_attr *ca, char *str) amp++; c = match_str2clr(buf); a = match_str2attr(amp, TRUE); - /* FIXME: match_str2clr & match_str2attr give config_error_add(), so this is useless */ + /* FIXME: match_str2clr & match_str2attr give config_error_add(), + so this is useless */ if (c >= CLR_MAX && a == -1) { /* try other way around */ c = match_str2clr(amp); @@ -2063,8 +2064,10 @@ color_attr_parse_str(color_attr *ca, char *str) } static int -optfn_menu_headings(int optidx, int req, boolean negated UNUSED, - char *opts, char *op UNUSED) +optfn_menu_headings( + int optidx, + int req, boolean negated, + char *opts, char *op) { if (req == do_init) { return optn_ok; @@ -2072,17 +2075,28 @@ optfn_menu_headings(int optidx, int req, boolean negated UNUSED, if (req == do_set) { color_attr ca; - if ((opts = string_for_env_opt(allopt[optidx].name, opts, FALSE)) - == empty_optstr) { - return optn_err; + if (op == empty_optstr) { + /* OPTIONS=menu_headings w/o value => no-color&inverse; + OPTIONS=!menu_headings => no-color&none */ + iflags.menu_headings.attr = negated ? ATR_NONE : ATR_INVERSE; + iflags.menu_headings.color = NO_COLOR; + return optn_ok; + } else if (negated) { /* 'op != empty_optstr' to get here */ + bad_negation(allopt[optidx].name, TRUE); + return optn_silenterr; } - if (!color_attr_parse_str(&ca, opts)) + if (!color_attr_parse_str(&ca, op)) return optn_err; iflags.menu_headings = ca; return optn_ok; } if (req == get_val || req == get_cnf_val) { - Sprintf(opts, "%s", color_attr_to_str(&iflags.menu_headings)); + char ca_buf[BUFSZ]; + + Strcpy(ca_buf, color_attr_to_str(&iflags.menu_headings)); + /* change "no color" to "no-color" or "light blue" to "light-blue" */ + (void) strNsubst(ca_buf, " ", "-", 0); + Strcpy(opts, ca_buf); return optn_ok; } if (req == do_handler) { @@ -2092,8 +2106,10 @@ optfn_menu_headings(int optidx, int req, boolean negated UNUSED, } static int -optfn_menuinvertmode(int optidx, int req, boolean negated UNUSED, - char *opts, char *op) +optfn_menuinvertmode( + int optidx, int req, + boolean negated UNUSED, + char *opts, char *op) { if (req == do_init) { return optn_ok; @@ -5996,8 +6012,8 @@ handler_menu_colors(void) goto menucolors_done; if (*mcbuf && test_regex_pattern(mcbuf, "MENUCOLORS regex") - && (mcclr = query_color((char *) 0)) != -1 - && (mcattr = query_attr((char *) 0)) != -1 + && (mcclr = query_color((char *) 0, NO_COLOR)) != -1 + && (mcattr = query_attr((char *) 0, ATR_NONE)) != -1 && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) { pline("Error adding the menu color."); wait_synch(); @@ -7361,13 +7377,12 @@ basic_menu_colors(boolean load_colors) RESTORE_WARNING_FORMAT_NONLITERAL int -query_color(const char *prompt) +query_color(const char *prompt, int dflt_color) { winid tmpwin; anything any; int i, pick_cnt; menu_item *picks = (menu_item *) 0; - int clr = NO_COLOR; /* replace user patterns with color name ones and force 'menucolors' On */ basic_menu_colors(TRUE); @@ -7380,9 +7395,9 @@ query_color(const char *prompt) break; any.a_int = i + 1; add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, - ATR_NONE, clr, colornames[i].name, - (colornames[i].color == NO_COLOR) ? MENU_ITEMFLAGS_SELECTED - : MENU_ITEMFLAGS_NONE); + ATR_NONE, NO_COLOR, colornames[i].name, + (colornames[i].color == dflt_color) ? MENU_ITEMFLAGS_SELECTED + : MENU_ITEMFLAGS_NONE); } end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color"); pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); @@ -7402,7 +7417,7 @@ query_color(const char *prompt) return i; } else if (pick_cnt == 0) { /* pick_cnt==0: explicitly picking preselected entry toggled it off */ - return NO_COLOR; + return dflt_color; } return -1; } @@ -7412,18 +7427,15 @@ query_color(const char *prompt) for status highlighting, multiple attributes are allowed [overkill; life would be much simpler if that were restricted to one also...] */ int -query_attr(const char *prompt) +query_attr(const char *prompt, int dflt_attr) { winid tmpwin; anything any; int i, pick_cnt; menu_item *picks = (menu_item *) 0; boolean allow_many = (prompt && !strncmpi(prompt, "Choose", 6)); - int default_attr = ATR_NONE; int clr = NO_COLOR; - if (prompt && strstri(prompt, "menu headings")) - default_attr = iflags.menu_headings.attr; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin, MENU_BEHAVE_STANDARD); any = cg.zeroany; @@ -7433,8 +7445,8 @@ query_attr(const char *prompt) any.a_int = i + 1; add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, attrnames[i].attr, clr, attrnames[i].name, - (attrnames[i].attr == default_attr) ? MENU_ITEMFLAGS_SELECTED - : MENU_ITEMFLAGS_NONE); + (attrnames[i].attr == dflt_attr) ? MENU_ITEMFLAGS_SELECTED + : MENU_ITEMFLAGS_NONE); } end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute"); pick_cnt = select_menu(tmpwin, allow_many ? PICK_ANY : PICK_ONE, &picks); @@ -7475,7 +7487,7 @@ query_attr(const char *prompt) j = picks[0].item.a_int - 1; /* pick_cnt==2: explicitly picked something other than the preselected entry */ - if (pick_cnt == 2 && attrnames[j].attr == default_attr) + if (pick_cnt == 2 && attrnames[j].attr == dflt_attr) j = picks[1].item.a_int - 1; k = attrnames[j].attr; } @@ -7483,7 +7495,7 @@ query_attr(const char *prompt) return k; } else if (pick_cnt == 0 && !allow_many) { /* PICK_ONE, preselected entry explicitly chosen */ - return default_attr; + return dflt_attr; } /* either ESC to explicitly cancel (pick_cnt==-1) or PICK_ANY with preselected entry toggled off and nothing chosen */ @@ -7495,10 +7507,10 @@ query_color_attr(color_attr *ca, const char *prompt) { int c, a; - c = query_color(prompt); + c = query_color(prompt, ca->color); if (c == -1) return FALSE; - a = query_attr(prompt); + a = query_attr(prompt, ca->attr); if (a == -1) return FALSE; ca->color = c;