From 699e65fa34d4df3ddf54fb7778e7a6d62911517b Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 23 Jun 2018 17:37:54 -0700 Subject: [PATCH] hilite_status attributes Take a step towards eliminating merging hilite_status rules during highlighting by creating a single rule instead of multiple ones when specifying multiple attributes for the same highlight via the 'O' command's menus. Old: (pick_one menu to pick a color) + (pick_one menu to pick an attribute) | hilite_status:title/always/red&bold (pick_one menu to pick a color) + (pick_one menu to pick an attribute) | hilite_status:title/always/red&blink New: (pick_one menu to pick a color) + (pick_any menu to pick attributes) | hilite_status:title/always/red&bold+blink At present, rule selection during highlighting still merges multiple applicable rules instead of finding the best one first, with the problems that entails. Bonus fix: a hilite_status rule for status conditions which specified "no attributes" would clear attributes for all previous condition rules rather than just the one(s) in that "no attributes" rule. --- doc/fixes36.2 | 6 ++++ src/botl.c | 65 ++++++++++++++---------------------------- src/options.c | 79 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 99 insertions(+), 51 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index fc7a7218e..7de916495 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -46,6 +46,12 @@ wishing for "glob of grey ooze" failed even though grey ooze is recognized as a variant spelling for gray ooze spells of healing and extra healing cast at monsters handled monster blindness inconsistently compared to other healing +when using the 'O' command to create a status highlight that specifies + multiple attributes (blink+inverse, &c), pick all of them in one menu + selection and create a single hilite_status rule instead of having + separate rules for each attribute to be merged when highlighting +highlighting status conditions would fail to use attributes if a rule with + them was followed by another one without (color only or color&normal) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/botl.c b/src/botl.c index 1548aef70..d7108a909 100644 --- a/src/botl.c +++ b/src/botl.c @@ -2282,11 +2282,11 @@ int sidx; else if (a == ATR_BOLD) cond_hilites[HL_ATTCLR_BOLD] |= conditions_bitmask; else if (a == ATR_NONE) { - cond_hilites[HL_ATTCLR_DIM] = 0UL; - cond_hilites[HL_ATTCLR_BLINK] = 0UL; - cond_hilites[HL_ATTCLR_ULINE] = 0UL; - cond_hilites[HL_ATTCLR_INVERSE] = 0UL; - cond_hilites[HL_ATTCLR_BOLD] = 0UL; + cond_hilites[HL_ATTCLR_DIM] &= ~conditions_bitmask; + cond_hilites[HL_ATTCLR_BLINK] &= ~conditions_bitmask; + cond_hilites[HL_ATTCLR_ULINE] &= ~conditions_bitmask; + cond_hilites[HL_ATTCLR_INVERSE] &= ~conditions_bitmask; + cond_hilites[HL_ATTCLR_BOLD] &= ~conditions_bitmask; } else { int k = match_str2clr(subfields[i]); @@ -2507,7 +2507,8 @@ status_hilite_linestr_gather_conditions() char condbuf[BUFSZ]; char *tmpattr; - (void) stripchars(clrbuf, " ", clr2colorname(clr)); + (void) strNsubst(strcpy(clrbuf, clr2colorname(clr)), + " ", "-", 0); tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ); if (tmpattr) Sprintf(eos(clrbuf), "&%s", tmpattr); @@ -2608,14 +2609,10 @@ struct hilite_s *hl; } split_clridx(hl->coloridx, &clr, &attr); - if (clr != NO_COLOR) - (void) stripchars(clrbuf, " ", clr2colorname(clr)); + (void) strNsubst(strcpy(clrbuf, clr2colorname(clr)), " ", "-", 0); if (attr != HL_UNDEF) { - tmpattr = hlattr2attrname(attr, attrbuf, BUFSZ); - if (tmpattr) - Sprintf(eos(clrbuf), "%s%s", - (clr != NO_COLOR) ? "&" : "", - tmpattr); + if ((tmpattr = hlattr2attrname(attr, attrbuf, BUFSZ)) != 0) + Sprintf(eos(clrbuf), "&%s", tmpattr); } Sprintf(buf, "%s/%s/%s", initblstats[hl->fld].fldname, behavebuf, clrbuf); @@ -3154,52 +3151,34 @@ choose_color: else goto choose_behavior; } - - atr = query_attr(attrqry); /* FIXME: pick multiple attrs */ + atr = query_attr(attrqry); if (atr == -1) goto choose_color; - if (atr == ATR_DIM) - atr = HL_DIM; - else if (atr == ATR_BLINK) - atr = HL_BLINK; - else if (atr == ATR_ULINE) - atr = HL_ULINE; - else if (atr == ATR_INVERSE) - atr = HL_INVERSE; - else if (atr == ATR_BOLD) - atr = HL_BOLD; - else if (atr == ATR_NONE) - atr = HL_NONE; - else - atr = HL_UNDEF; - - if (clr == -1) - clr = NO_COLOR; if (behavior == BL_TH_CONDITION) { char clrbuf[BUFSZ]; char attrbuf[BUFSZ]; char *tmpattr; - if (atr == HL_DIM) + if (atr & HL_DIM) cond_hilites[HL_ATTCLR_DIM] |= cond; - else if (atr == HL_BLINK) + else if (atr & HL_BLINK) cond_hilites[HL_ATTCLR_BLINK] |= cond; - else if (atr == HL_ULINE) + else if (atr & HL_ULINE) cond_hilites[HL_ATTCLR_ULINE] |= cond; - else if (atr == HL_INVERSE) + else if (atr & HL_INVERSE) cond_hilites[HL_ATTCLR_INVERSE] |= cond; - else if (atr == HL_BOLD) + else if (atr & HL_BOLD) cond_hilites[HL_ATTCLR_BOLD] |= cond; else if (atr == HL_NONE) { - cond_hilites[HL_ATTCLR_DIM] = 0UL; - cond_hilites[HL_ATTCLR_BLINK] = 0UL; - cond_hilites[HL_ATTCLR_ULINE] = 0UL; - cond_hilites[HL_ATTCLR_INVERSE] = 0UL; - cond_hilites[HL_ATTCLR_BOLD] = 0UL; + cond_hilites[HL_ATTCLR_DIM] &= ~cond; + cond_hilites[HL_ATTCLR_BLINK] &= ~cond; + cond_hilites[HL_ATTCLR_ULINE] &= ~cond; + cond_hilites[HL_ATTCLR_INVERSE] &= ~cond; + cond_hilites[HL_ATTCLR_BOLD] &= ~cond; } cond_hilites[clr] |= cond; - (void) stripchars(clrbuf, " ", clr2colorname(clr)); + (void) strNsubst(strcpy(clrbuf, clr2colorname(clr)), " ", "-", 0); tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ); if (tmpattr) Sprintf(eos(clrbuf), "&%s", tmpattr); diff --git a/src/options.c b/src/options.c index fbe568fb2..b07c7b818 100644 --- a/src/options.c +++ b/src/options.c @@ -1417,19 +1417,31 @@ const char *prompt; break; any.a_int = i + 1; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name, - MENU_UNSELECTED); + (colornames[i].color == NO_COLOR) ? MENU_SELECTED + : MENU_UNSELECTED); } end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color"); pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); destroy_nhwindow(tmpwin); if (pick_cnt > 0) { - i = colornames[picks->item.a_int - 1].color; + i = colornames[picks[0].item.a_int - 1].color; + /* pick_cnt==2: explicitly picked something other than the + preselected entry */ + if (pick_cnt == 2 && i == NO_COLOR) + i = colornames[picks[1].item.a_int - 1].color; free((genericptr_t) picks); return i; + } else if (pick_cnt == 0) { + /* pick_cnt==0: explicitly picking preselected entry toggled it off */ + return NO_COLOR; } return -1; } +/* ask about highlighting attribute; for menu headers and menu + coloring patterns, only one attribute at a time is allowed; + for status highlighting, multiple attributes are allowed [overkill; + life would be much simpler if that were restricted to one also...] */ int query_attr(prompt) const char *prompt; @@ -1438,7 +1450,11 @@ const char *prompt; 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; + if (prompt && strstri(prompt, "menu headings")) + default_attr = iflags.menu_headings; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); any = zeroany; @@ -1447,16 +1463,61 @@ const char *prompt; break; any.a_int = i + 1; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr, - attrnames[i].name, MENU_UNSELECTED); + attrnames[i].name, + (attrnames[i].attr == default_attr) ? MENU_SELECTED + : MENU_UNSELECTED); } end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute"); - pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); + pick_cnt = select_menu(tmpwin, allow_many ? PICK_ANY: PICK_ONE, &picks); destroy_nhwindow(tmpwin); if (pick_cnt > 0) { - i = attrnames[picks->item.a_int - 1].attr; + int j, k = 0; + + if (allow_many) { + /* PICK_ANY, with one preselected entry which should be + excluded if any other choices were picked */ + for (i = 0; i < pick_cnt; ++i) { + j = picks[i].item.a_int - 1; + if (attrnames[j].attr != ATR_NONE || pick_cnt == 1) { + switch (attrnames[j].attr) { + case ATR_DIM: + k |= HL_DIM; + break; + case ATR_BLINK: + k |= HL_BLINK; + break; + case ATR_ULINE: + k |= HL_ULINE; + break; + case ATR_INVERSE: + k |= HL_INVERSE; + break; + case ATR_BOLD: + k |= HL_BOLD; + break; + case ATR_NONE: + k = HL_NONE; + break; + } + } + } + } else { + /* PICK_ONE, but might get 0 or 2 due to preselected entry */ + 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) + j = picks[1].item.a_int - 1; + k = attrnames[j].attr; + } free((genericptr_t) picks); - return i; + return k; + } else if (pick_cnt == 0 && !allow_many) { + /* PICK_ONE, preselected entry explicitly chosen */ + return default_attr; } + /* either ESC to explicitly cancel (pick_cnt==-1) or + PICK_ANY with preselected entry toggled off and nothing chosen */ return -1; } @@ -4872,6 +4933,7 @@ boolean setinitial, setfromfile; const char *sattr, *sclr; menu_item *pick_list = (menu_item *) 0; struct menucoloring *tmp = menu_colorings; + char clrbuf[QBUFSZ]; tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); @@ -4879,11 +4941,12 @@ boolean setinitial, setfromfile; mc_idx = 0; while (tmp) { sattr = attr2attrname(tmp->attr); - sclr = clr2colorname(tmp->color); + sclr = strcpy(clrbuf, clr2colorname(tmp->color)); + (void) strNsubst(clrbuf, " ", "-", 0); any.a_int = ++mc_idx; /* construct suffix */ Sprintf(buf, "\"\"=%s%s%s", sclr, - (tmp->attr != ATR_NONE) ? " & " : "", + (tmp->attr != ATR_NONE) ? "&" : "", (tmp->attr != ATR_NONE) ? sattr : ""); /* now main string */ ln = sizeof buf - strlen(buf) - 1; /* length available */