diff --git a/doc/fixes36.2 b/doc/fixes36.2 index edbd2c4ca..864175d99 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.290 $ $NHDT-Date: 1553904170 2019/03/30 00:02:50 $ +$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.291 $ $NHDT-Date: 1554017610 2019/03/31 07:33:30 $ This fixes36.2 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.1 in April 2018. Please note, however, @@ -403,6 +403,9 @@ Valkyrie quest was supposed to have a 50:50 chance that northern drawbridge lowered: 3/8, S down+N up: 3/8, N down+S up: 1/8, both raised: 1/8 shorten the getpos prompt for teleport destination so that it won't yield a --More-- prompt for the help hint (--More-- still possible when riding) +once a status highlight for a temporary rule ('up', 'down', 'changed') timed + out, further spurious status updates (evaluating all fields) would + occur every 'statushilites' turns even if no fields had changed Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/botl.c b/src/botl.c index 441581292..545e5cd6a 100644 --- a/src/botl.c +++ b/src/botl.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 botl.c $NHDT-Date: 1553993169 2019/03/31 00:46:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.138 $ */ +/* NetHack 3.6 botl.c $NHDT-Date: 1554017610 2019/03/31 07:33:30 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.139 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -399,6 +399,8 @@ char *buf; /* structure that tracks the status details in the core */ +#define MAXVALWIDTH 80 /* actually less, but was using 80 to allocate title + * and leveldesc then using QBUFSZ everywhere else */ #ifdef STATUS_HILITES struct hilite_s { enum statusfields fld; @@ -406,7 +408,7 @@ struct hilite_s { unsigned anytype; anything value; int behavior; - char textmatch[QBUFSZ]; + char textmatch[MAXVALWIDTH]; enum relationships rel; int coloridx; struct hilite_s *next; @@ -425,30 +427,29 @@ struct istat_s { enum statusfields idxmax; enum statusfields fld; #ifdef STATUS_HILITES + struct hilite_s *hilite_rule; /* the entry, if any, in 'thresholds' + * list that currently applies */ struct hilite_s *thresholds; #endif }; - STATIC_DCL void NDECL(init_blstats); STATIC_DCL char *FDECL(anything_to_s, (char *, anything *, int)); STATIC_OVL int FDECL(percentage, (struct istat_s *, struct istat_s *)); STATIC_OVL int FDECL(compare_blstats, (struct istat_s *, struct istat_s *)); -STATIC_DCL boolean FDECL(evaluate_and_notify_windowport_field, - (int, boolean *, int, int)); -STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int, int)); +STATIC_DCL boolean FDECL(eval_notify_windowport_field, (int, boolean *, int)); +STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int)); #ifdef STATUS_HILITES STATIC_DCL boolean FDECL(hilite_reset_needed, (struct istat_s *, long)); STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int)); STATIC_DCL boolean FDECL(is_ltgt_percentnumber, (const char *)); STATIC_DCL boolean FDECL(has_ltgt_percentnumber, (const char *)); -STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ],BOOLEAN_P)); +STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ], BOOLEAN_P)); STATIC_DCL boolean FDECL(parse_condition, (char (*)[QBUFSZ], int)); STATIC_DCL boolean FDECL(noneoftheabove, (const char *)); -STATIC_DCL void FDECL(merge_bestcolor, (int *, int)); -STATIC_DCL void FDECL(get_hilite_color, (int, int, genericptr_t, int, - int, int *)); +STATIC_DCL struct hilite_s *FDECL(get_hilite, (int, int, genericptr_t, + int, int, int *)); STATIC_DCL unsigned long FDECL(match_str2conditionbitmask, (const char *)); STATIC_DCL unsigned long FDECL(str2conditionbitmask, (char *)); STATIC_DCL void FDECL(split_clridx, (int, int *, int *)); @@ -466,18 +467,25 @@ STATIC_DCL int FDECL(status_hilite_menu_choose_updownboth, (int, const char *, BOOLEAN_P, BOOLEAN_P)); STATIC_DCL boolean FDECL(status_hilite_menu_add, (int)); #define has_hilite(i) (blstats[0][(i)].thresholds) +/* TH_UPDOWN encompasses specific 'up' and 'down' also general 'changed' */ +#define Is_Temp_Hilite(rule) ((rule) && (rule)->behavior == BL_TH_UPDOWN) + +/* pointers to current hilite rule and list of this field's defined rules */ +#define INIT_THRESH , (struct hilite_s *) 0, (struct hilite_s *) 0 +#else /* !STATUS_HILITES */ +#define INIT_THRESH /*empty*/ #endif #define INIT_BLSTAT(name, fmtstr, anytyp, wid, fld) \ { name, fmtstr, 0L, FALSE, anytyp, { (genericptr_t) 0 }, (char *) 0, \ - wid, -1, fld } + wid, -1, fld INIT_THRESH } #define INIT_BLSTATP(name, fmtstr, anytyp, wid, maxfld, fld) \ { name, fmtstr, 0L, FALSE, anytyp, { (genericptr_t) 0 }, (char *) 0, \ - wid, maxfld, fld } + wid, maxfld, fld INIT_THRESH } /* If entries are added to this, botl.h will require updating too */ STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = { - INIT_BLSTAT("title", "%s", ANY_STR, 80, BL_TITLE), + INIT_BLSTAT("title", "%s", ANY_STR, MAXVALWIDTH, BL_TITLE), INIT_BLSTAT("strength", " St:%s", ANY_INT, 10, BL_STR), INIT_BLSTAT("dexterity", " Dx:%s", ANY_INT, 10, BL_DX), INIT_BLSTAT("constitution", " Co:%s", ANY_INT, 10, BL_CO), @@ -498,18 +506,18 @@ STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = { INIT_BLSTAT("hunger", " %s", ANY_INT, 40, BL_HUNGER), INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP), INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX), - INIT_BLSTAT("dungeon-level", "%s", ANY_STR, 80, BL_LEVELDESC), + INIT_BLSTAT("dungeon-level", "%s", ANY_STR, MAXVALWIDTH, BL_LEVELDESC), INIT_BLSTAT("experience", "/%s", ANY_LONG, 20, BL_EXP), INIT_BLSTAT("condition", "%s", ANY_MASK32, 0, BL_CONDITION) }; #undef INIT_BLSTATP #undef INIT_BLSTAT +#undef INIT_THRESH struct istat_s blstats[2][MAXBLSTATS]; static boolean blinit = FALSE, update_all = FALSE; static boolean valset[MAXBLSTATS]; -unsigned long blcolormasks[CLR_MAX]; static long bl_hilite_moves = 0L; /* we don't put this next declaration in #ifdef STATUS_HILITES. @@ -519,7 +527,7 @@ static long bl_hilite_moves = 0L; * the final argument of status_update, with or * without STATUS_HILITES. */ -unsigned long cond_hilites[BL_ATTCLR_MAX]; +static unsigned long cond_hilites[BL_ATTCLR_MAX]; void bot_via_windowport() @@ -528,13 +536,13 @@ bot_via_windowport() char buf[BUFSZ]; const char *titl; register char *nb; - int i, idx_p, cap; + int i, cap; long money; if (!blinit) panic("bot before init."); - idx_p = idx; + /* toggle from previous iteration */ idx = 1 - idx; /* 0 -> 1, 1 -> 0 */ /* clear the "value set" indicators */ @@ -699,12 +707,12 @@ bot_via_windowport() blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY; if (u.usteed) blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE; - evaluate_and_notify_windowport(valset, idx, idx_p); + evaluate_and_notify_windowport(valset, idx); } STATIC_OVL boolean -evaluate_and_notify_windowport_field(fld, valsetlist, idx, idx_p) -int fld, idx, idx_p; +eval_notify_windowport_field(fld, valsetlist, idx) +int fld, idx; boolean *valsetlist; { static int oldrndencode = 0; @@ -720,7 +728,7 @@ boolean *valsetlist; */ anytype = blstats[idx][fld].anytype; curr = &blstats[idx][fld]; - prev = &blstats[idx_p][fld]; + prev = &blstats[1 - idx][fld]; color = NO_COLOR; chg = update_all ? 0 : compare_blstats(prev, curr); @@ -753,7 +761,7 @@ boolean *valsetlist; reset = FALSE; #ifdef STATUS_HILITES - if (!update_all && !chg) { + if (!update_all && !chg && curr->time) { reset = hilite_reset_needed(prev, bl_hilite_moves); if (reset) curr->time = prev->time = 0L; @@ -769,9 +777,11 @@ boolean *valsetlist; if (anytype != ANY_MASK32) { #ifdef STATUS_HILITES - if ((chg || *curr->val)) { - get_hilite_color(idx, fld, (genericptr_t) &curr->a, - chg, pc, &color); + if (chg || *curr->val) { + curr->hilite_rule = get_hilite(idx, fld, + (genericptr_t) &curr->a, + chg, pc, &color); + prev->hilite_rule = curr->hilite_rule; if (chg == 2) { color = NO_COLOR; chg = 0; @@ -779,11 +789,11 @@ boolean *valsetlist; } #endif /* STATUS_HILITES */ status_update(fld, (genericptr_t) curr->val, - chg, pc, color, &cond_hilites[0]); + chg, pc, color, (unsigned long *) 0); } else { /* Color for conditions is done through cond_hilites[] */ - status_update(fld, (genericptr_t) &curr->a.a_ulong, chg, pc, - color, &cond_hilites[0]); + status_update(fld, (genericptr_t) &curr->a.a_ulong, + chg, pc, color, cond_hilites); } curr->chg = prev->chg = TRUE; updated = TRUE; @@ -792,8 +802,8 @@ boolean *valsetlist; } static void -evaluate_and_notify_windowport(valsetlist, idx, idx_p) -int idx, idx_p; +evaluate_and_notify_windowport(valsetlist, idx) +int idx; boolean *valsetlist; { int i, updated = 0, notpresent = 0; @@ -810,7 +820,7 @@ boolean *valsetlist; notpresent++; continue; } - if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p)) + if (eval_notify_windowport_field(i, valsetlist, idx)) updated++; } /* @@ -838,13 +848,13 @@ boolean *valsetlist; */ if (context.botlx && (windowprocs.wincap2 & WC2_RESET_STATUS) != 0L) status_update(BL_RESET, (genericptr_t) 0, 0, 0, - NO_COLOR, &cond_hilites[0]); + NO_COLOR, (unsigned long *) 0); else if ((updated || context.botlx) && (windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L) status_update(BL_FLUSH, (genericptr_t) 0, 0, 0, - NO_COLOR, &cond_hilites[0]); + NO_COLOR, (unsigned long *) 0); - context.botl = context.botlx = 0; + context.botl = context.botlx = FALSE; update_all = FALSE; } @@ -852,11 +862,12 @@ void status_eval_next_unhilite() { int i; - struct istat_s *curr = NULL; + struct istat_s *curr; long next_unhilite, this_unhilite; - bl_hilite_moves = moves; - /* figure out when the next unhilight needs to be performed */ + bl_hilite_moves = moves; /* simpllfied; used to try to encode fractional + * amounts for multiple moves within same turn */ + /* figure out whether an unhilight needs to be performed now */ next_unhilite = 0L; for (i = 0; i < MAXBLSTATS; ++i) { curr = &blstats[0][i]; /* blstats[0][*].time == blstats[1][*].time */ @@ -865,10 +876,17 @@ status_eval_next_unhilite() struct istat_s *prev = &blstats[1][i]; #ifdef STATUS_HILITES - curr->time = prev->time = (bl_hilite_moves + iflags.hilite_delta); + if (Is_Temp_Hilite(curr->hilite_rule)) + curr->time = prev->time = (bl_hilite_moves + + iflags.hilite_delta); + else + curr->time = prev->time = 0L; #endif curr->chg = prev->chg = FALSE; + context.botl = TRUE; } + if (context.botl) + continue; /* just process other blstats[][].time and .chg */ this_unhilite = curr->time; if (this_unhilite > 0L @@ -876,21 +894,22 @@ status_eval_next_unhilite() #ifdef STATUS_HILITES && hilite_reset_needed(curr, this_unhilite + 1L) #endif - ) + ) { next_unhilite = this_unhilite; + if (next_unhilite < bl_hilite_moves) + context.botl = TRUE; + } } - if (next_unhilite > 0L && next_unhilite < bl_hilite_moves) - context.botl = TRUE; } void status_initialize(reassessment) -boolean - reassessment; /* TRUE = just reassess fields w/o other initialization*/ +boolean reassessment; /* TRUE: just recheck fields w/o other initialization */ { + enum statusfields fld; + boolean fldenabl; int i; - const char *fieldfmt = (const char *) 0; - const char *fieldname = (const char *) 0; + const char *fieldfmt, *fieldname; if (!reassessment) { if (blinit) @@ -898,22 +917,22 @@ boolean init_blstats(); (*windowprocs.win_status_init)(); blinit = TRUE; + } else if (!blinit) { + panic("status 'reassess' before init"); } for (i = 0; i < MAXBLSTATS; ++i) { - enum statusfields fld = initblstats[i].fld; - boolean fldenabled = (fld == BL_SCORE) ? flags.showscore - : (fld == BL_XP) ? (boolean) !Upolyd - : (fld == BL_HD) ? (boolean) Upolyd - : (fld == BL_TIME) ? flags.time - : (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd) - : TRUE; + fld = initblstats[i].fld; + fldenabl = (fld == BL_SCORE) ? flags.showscore + : (fld == BL_TIME) ? flags.time + : (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd) + : (fld == BL_XP) ? (boolean) !Upolyd + : (fld == BL_HD) ? (boolean) Upolyd + : TRUE; fieldname = initblstats[i].fldname; - if (fld == BL_TITLE && iflags.wc2_hitpointbar) - fieldfmt = "%-30s"; - else - fieldfmt = initblstats[i].fldfmt; - status_enablefield(fld, fieldname, fieldfmt, fldenabled); + fieldfmt = (fld == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30.30s" + : initblstats[i].fldfmt; + status_enablefield(fld, fieldname, fieldfmt, fldenabl); } update_all = TRUE; } @@ -934,14 +953,17 @@ status_finish() if (blstats[1][i].val) free((genericptr_t) blstats[1][i].val), blstats[1][i].val = 0; #ifdef STATUS_HILITES + /* pointer to an entry in thresholds list; Null it out since + that list is about to go away */ + blstats[0][i].hilite_rule = blstats[1][i].hilite_rule = 0; if (blstats[0][i].thresholds) { - struct hilite_s *temp, *next = 0; + struct hilite_s *temp, *next; for (temp = blstats[0][i].thresholds; temp; temp = next) { next = temp->next; free((genericptr_t) temp); - blstats[0][i].thresholds = blstats[1][i].thresholds = 0; } + blstats[0][i].thresholds = blstats[1][i].thresholds = 0; } #endif /* STATUS_HILITES */ } @@ -957,9 +979,7 @@ init_blstats() impossible("init_blstats called more than once."); return; } - - initalready = TRUE; - for (i = BEFORE; i <= NOW; ++i) { + for (i = 0; i <= 1; ++i) { for (j = 0; j < MAXBLSTATS; ++j) { #ifdef STATUS_HILITES struct hilite_s *keep_hilite_chain = blstats[i][j].thresholds; @@ -977,6 +997,7 @@ init_blstats() #endif } } + initalready = TRUE; } /* @@ -1327,26 +1348,19 @@ hilite_reset_needed(bl_p, augmented_time) struct istat_s *bl_p; long augmented_time; { - struct hilite_s *tl = bl_p->thresholds; - /* * This 'multi' handling may need some tuning... */ if (multi) return FALSE; + if (!Is_Temp_Hilite(bl_p->hilite_rule)) + return FALSE; + if (bl_p->time == 0 || bl_p->time >= augmented_time) return FALSE; - while (tl) { - /* only this style times out (includes general 'changed' - as well as specific 'up' and 'down') */ - if (tl->behavior == BL_TH_UPDOWN) - return TRUE; - tl = tl->next; - } - - return FALSE; + return TRUE; } /* called by options handling when 'statushilites' boolean is toggled */ @@ -1377,33 +1391,13 @@ const char *hl_text; return FALSE; } -STATIC_OVL void -merge_bestcolor(bestcolor, newcolor) -int *bestcolor; -int newcolor; -{ - int natr = HL_UNDEF, nclr = NO_COLOR; - - split_clridx(newcolor, &nclr, &natr); - - if (nclr != NO_COLOR) - *bestcolor = (*bestcolor & 0xff00) | nclr; - - if (natr != HL_UNDEF) { - if (natr == HL_NONE) - *bestcolor = *bestcolor & 0x00ff; /* reset all attributes */ - else - *bestcolor |= (natr << 8); /* merge attributes */ - } -} - /* - * get_hilite_color + * get_hilite * - * Figures out, based on the value and the direction it is moving, - * the color that the field should be displayed in. + * Returns, based on the value and the direction it is moving, + * the highlight rule that applies to the specified field. * - * Provide get_hilite_color() with the following to work with: + * Provide get_hilite() with the following to work with: * actual value vp * useful for BL_TH_VAL_ABSOLUTE * indicator of down, up, or the same (-1, 1, 0) chg @@ -1412,28 +1406,22 @@ int newcolor; * useful for BL_TH_VAL_PERCENTAGE * * Get back: - * color based on user thresholds set in config file. - * The rightmost 8 bits contain a color index. - * The 8 bits to the left of that contain - * the attribute bits. - * color = 0x00FF - * attrib= 0xFF00 + * pointer to rule that applies; Null if no rule does. */ -STATIC_OVL void -get_hilite_color(idx, fldidx, vp, chg, pc, colorptr) +STATIC_OVL struct hilite_s * +get_hilite(idx, fldidx, vp, chg, pc, colorptr) int idx, fldidx, chg, pc; genericptr_t vp; int *colorptr; { - int bestcolor = NO_COLOR; - struct hilite_s *hl; + struct hilite_s *hl, *rule = 0; anything *value = (anything *) vp; char *txtstr; - if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS) - return; + if (fldidx < 0 || fldidx >= MAXBLSTATS) + return (struct hilite_s *) 0; - if (blstats[idx][fldidx].thresholds) { + if (has_hilite(fldidx)) { int dt; /* there are hilites set here */ int max_pc = -1, min_pc = 101; @@ -1447,7 +1435,7 @@ int *colorptr; perc_or_abs = FALSE; /* min_/max_ are used to track best fit */ - for (hl = blstats[idx][fldidx].thresholds; hl; hl = hl->next) { + for (hl = blstats[0][fldidx].thresholds; hl; hl = hl->next) { dt = initblstats[fldidx].anytype; /* only needed for 'absolute' */ /* if we've already matched a temporary highlight, it takes precedence over all persistent ones; we still process @@ -1462,7 +1450,7 @@ int *colorptr; switch (hl->behavior) { case BL_TH_VAL_PERCENTAGE: /* percent values are always ANY_INT */ if (hl->rel == EQ_VALUE && pc == hl->value.a_int) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_pc = max_pc = hl->value.a_int; exactmatch = perc_or_abs = TRUE; } else if (exactmatch) { @@ -1470,25 +1458,25 @@ int *colorptr; } else if (hl->rel == LT_VALUE && (pc < hl->value.a_int) && (hl->value.a_int <= min_pc)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_pc = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == LE_VALUE && (pc <= hl->value.a_int) && (hl->value.a_int <= min_pc)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_pc = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == GT_VALUE && (pc > hl->value.a_int) && (hl->value.a_int >= max_pc)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_pc = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == GE_VALUE && (pc >= hl->value.a_int) && (hl->value.a_int >= max_pc)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_pc = hl->value.a_int; perc_or_abs = TRUE; } @@ -1497,13 +1485,13 @@ int *colorptr; /* specific 'up' or 'down' takes precedence over general 'changed' regardless of their order in the rule set */ if (chg < 0 && hl->rel == LT_VALUE) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; updown = TRUE; } else if (chg > 0 && hl->rel == GT_VALUE) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; updown = TRUE; } else if (chg != 0 && hl->rel == EQ_VALUE && !updown) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; changed = TRUE; } break; @@ -1516,7 +1504,7 @@ int *colorptr; if (dt == ANY_INT) { if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_ival = max_ival = hl->value.a_int; exactmatch = perc_or_abs = TRUE; } else if (exactmatch) { @@ -1524,32 +1512,32 @@ int *colorptr; } else if (hl->rel == LT_VALUE && (value->a_int < hl->value.a_int) && (hl->value.a_int <= min_ival)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_ival = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == LE_VALUE && (value->a_int <= hl->value.a_int) && (hl->value.a_int <= min_ival)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_ival = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == GT_VALUE && (value->a_int > hl->value.a_int) && (hl->value.a_int >= max_ival)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_ival = hl->value.a_int; perc_or_abs = TRUE; } else if (hl->rel == GE_VALUE && (value->a_int >= hl->value.a_int) && (hl->value.a_int >= max_ival)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_ival = hl->value.a_int; perc_or_abs = TRUE; } } else { /* ANY_LONG */ if (hl->rel == EQ_VALUE && hl->value.a_long == value->a_long) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_lval = max_lval = hl->value.a_long; exactmatch = perc_or_abs = TRUE; } else if (exactmatch) { @@ -1557,25 +1545,25 @@ int *colorptr; } else if (hl->rel == LT_VALUE && (value->a_long < hl->value.a_long) && (hl->value.a_long <= min_lval)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_lval = hl->value.a_long; perc_or_abs = TRUE; } else if (hl->rel == LE_VALUE && (value->a_long <= hl->value.a_long) && (hl->value.a_long <= min_lval)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; min_lval = hl->value.a_long; perc_or_abs = TRUE; } else if (hl->rel == GT_VALUE && (value->a_long > hl->value.a_long) && (hl->value.a_long >= max_lval)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_lval = hl->value.a_long; perc_or_abs = TRUE; } else if (hl->rel == GE_VALUE && (value->a_long >= hl->value.a_long) && (hl->value.a_long >= max_lval)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; max_lval = hl->value.a_long; perc_or_abs = TRUE; } @@ -1588,18 +1576,18 @@ int *colorptr; txtstr += (strlen(plname) + sizeof " the " - sizeof ""); if (hl->rel == TXT_VALUE && hl->textmatch[0]) { if (fuzzymatch(hl->textmatch, txtstr, "\" -_", TRUE)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; exactmatch = TRUE; } else if (exactmatch) { ; /* already found best fit, skip "noneoftheabove" */ } else if (fldidx == BL_TITLE && Upolyd && noneoftheabove(hl->textmatch)) { - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; } } break; case BL_TH_ALWAYS_HILITE: - merge_bestcolor(&bestcolor, hl->coloridx); + rule = hl; break; case BL_TH_NONE: break; @@ -1608,8 +1596,8 @@ int *colorptr; } } } - *colorptr = bestcolor; - return; + *colorptr = rule ? rule->coloridx : NO_COLOR; + return rule; } STATIC_OVL void @@ -2119,9 +2107,9 @@ boolean from_configfile; hilite.anytype = dt; - if (hilite.behavior == BL_TH_TEXTMATCH && txt - && strlen(txt) < QBUFSZ - 1) { - Strcpy(hilite.textmatch, txt); + if (hilite.behavior == BL_TH_TEXTMATCH && txt) { + (void) strncpy(hilite.textmatch, txt, sizeof hilite.textmatch); + hilite.textmatch[sizeof hilite.textmatch - 1] = '\0'; (void) trimspaces(hilite.textmatch); } @@ -2307,6 +2295,15 @@ int sidx; /*3.6.1: OPTION=hilite_status: condition/stone+slime+foodPois/red&inverse */ + /* + * TODO? + * It would be simpler to treat each condition (also hunger state + * and encumbrance level) as if it were a separate field. That + * way they could have either or both 'changed' temporary rule and + * 'always' persistent rule and wouldn't need convoluted access to + * the intended color and attributes. + */ + sidx++; while(s[sidx]) { int sf = 0; /* subfield count */ @@ -2410,17 +2407,15 @@ clear_status_hilites() int i; for (i = 0; i < MAXBLSTATS; ++i) { - if (blstats[0][i].thresholds) { - struct hilite_s *temp = blstats[0][i].thresholds, - *next = (struct hilite_s *)0; - while (temp) { - next = temp->next; - free(temp); - blstats[0][i].thresholds = (struct hilite_s *)0; - blstats[1][i].thresholds = blstats[0][i].thresholds; - temp = next; - } + struct hilite_s *temp, *next; + + for (temp = blstats[0][i].thresholds; temp; temp = next) { + next = temp->next; + free(temp); } + blstats[0][i].thresholds = blstats[1][i].thresholds = 0; + /* pointer into thresholds list, now stale */ + blstats[0][i].hilite_rule = blstats[1][i].hilite_rule = 0; } } @@ -3200,7 +3195,7 @@ choose_value: Strcpy(hilite.textmatch, hutxt[rv]); } else if (fld == BL_TITLE) { const char *rolelist[3 * 9 + 1]; - char mbuf[QBUFSZ], fbuf[QBUFSZ], obuf[QBUFSZ]; + char mbuf[MAXVALWIDTH], fbuf[MAXVALWIDTH], obuf[MAXVALWIDTH]; int i, j, rv; for (i = j = 0; i < 9; i++) { @@ -3247,7 +3242,7 @@ choose_value: goto choose_behavior; hilite.rel = TXT_VALUE; - if (strlen(inbuf) < QBUFSZ - 1) + if (strlen(inbuf) < sizeof hilite.textmatch) Strcpy(hilite.textmatch, inbuf); else return FALSE; @@ -3357,25 +3352,25 @@ int id; return TRUE; } else { int fld = hlstr->fld; - struct hilite_s *hl = blstats[0][fld].thresholds; - struct hilite_s *hlprev = (struct hilite_s *) 0; + struct hilite_s *hl, *hlprev = (struct hilite_s *) 0; - if (hl) { - while (hl) { - if (hlstr->hl == hl) { - if (hlprev) { - hlprev->next = hl->next; - } else { - blstats[0][fld].thresholds = hl->next; - blstats[1][fld].thresholds = - blstats[0][fld].thresholds; - } - free((genericptr_t) hl); - return TRUE; + for (hl = blstats[0][fld].thresholds; hl; hl = hl->next) { + if (hlstr->hl == hl) { + if (hlprev) { + hlprev->next = hl->next; + } else { + blstats[0][fld].thresholds = hl->next; + blstats[1][fld].thresholds = blstats[0][fld].thresholds; } - hlprev = hl; - hl = hl->next; + if (blstats[0][fld].hilite_rule == hl) { + blstats[0][fld].hilite_rule + = blstats[1][fld].hilite_rule = (struct hilite_s *) 0; + blstats[0][fld].time = blstats[1][fld].time = 0L; + } + free((genericptr_t) hl); + return TRUE; } + hlprev = hl; } } return FALSE;