diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 576701c53..c200e88f3 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -104,6 +104,13 @@ wizard mode ^I^I didn't make temporary identifications become persistent if the build configuration makes plain 'char' unsigned wizard mode #wizidentify didn't disclose extra information for unID'd items if key bindings took away ^I and didn't bind #wizidentify to another key +make transformation message of a deliberate apply of a figurine seem a bit + less definite when blind and place unseen monster marker at the spot + you think it should be +add window port status_update() value BL_RESET to use as a flag to + redraw all status fields, distinguished from BL_FLUSH which now only + specifies that the bot() call has completed so any buffered changes + should now be rendered Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository @@ -112,12 +119,15 @@ fix access violation when --debug:xxxx has no other args after it setting the inverse attribute for gold had the space before "$:" getting highlighted along with the gold field sortloot segfaulted when filtering a subset of items (seen with 'A' command) +tty: turn off an optimization that is the suspected cause of Windows reported + partial status lines following level changes Platform- and/or Interface-Specific Fixes ----------------------------------------- windows-gui: In nethackw, there could be conflicts between menu accelerators - and an extra choice accelerator to fix H7132. + and an extra choice accelerator to fix H7132. +windows-gui: recognize new BL_RESET in status_update; behavior currently the same windows-tty: Specify both width and height when creating font for width testing windows-tty: To counter lag problems that were occuring with the Win32 console port, implement a console back buffer to reduce the number of calls @@ -134,6 +144,8 @@ windows-tty: Use nhraykey by default if the players keyboard layout is windows-tty: We now support changing altkeyhandler in game windows: Added ntassert() mechanism for Windows based port use tty: significant optimizations for performance and per field rendering +tty: use WC2_FLUSH_STATUS to buffer changes until BL_FLUSH is received +tty: support BL_RESET in status_update to force an update to all status fields unix: Makefile.src and Makefile.utl inadvertently relied on a 'gnu make' extension when using $(VERBOSEMAKE) to reduce build-time feedback; replace with $(QUIETCC) which operates the same but defaults to @@ -154,6 +166,9 @@ sortloot option has been enhanced to improve object ordering; primarily, within each class or sub-class of objects YAFM when stumbling on an undetected monster while hallucinating Make it clear when a leprechaun dodges your attack +wizard mode #wizidentify can now select individual items for permanent + identification and don't display the selection to permanently + identify everything if everything is already fully identified Code Cleanup and Reorganization diff --git a/doc/window.doc b/doc/window.doc index e648b23a4..59b90255d 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -412,6 +412,10 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage, int color BL_LEVELDESC, BL_EXP, BL_CONDITION -- fldindex could also be BL_FLUSH (-1), which is not really a field index, but is a special trigger to tell the + windowport that it should output all changes received + to this point. It marks the end of a bot() cycle. + -- fldindex could also be BL_RESET (-2), which is not really + a field index, but is a special advisory to to tell the windowport that it should redisplay all its status fields, even if no changes have been presented to it. -- ptr is usually a "char *", unless fldindex is BL_CONDITION. diff --git a/include/botl.h b/include/botl.h index 4d9347088..9e4e36595 100644 --- a/include/botl.h +++ b/include/botl.h @@ -28,8 +28,10 @@ Astral Plane \GXXXXNNNN:123456 HP:1234(1234) Pw:1234(1234) AC:-127 #endif enum statusfields { - BL_CHARACTERISTICS = -2, /* alias for BL_STR..BL_CH */ - BL_FLUSH = -1, BL_TITLE = 0, + BL_CHARACTERISTICS = -3, /* alias for BL_STR..BL_CH */ + BL_RESET = -2, /* Force everything to redisplay */ + BL_FLUSH = -1, /* Finished cycling through bot fields */ + BL_TITLE = 0, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, /* 1..6 */ BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, /* 7..12 */ BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, /* 13..18 */ diff --git a/include/extern.h b/include/extern.h index bd1924a6b..abd4be118 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1525012590 2018/04/29 14:36:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.629 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1535812936 2018/09/01 14:42:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.636 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -973,6 +973,7 @@ E int FDECL(askchain, (struct obj **, const char *, int, int (*)(OBJ_P), int (*)(OBJ_P), int, const char *)); E void FDECL(fully_identify_obj, (struct obj *)); E int FDECL(identify, (struct obj *)); +E int FDECL(count_unidentified, (struct obj *)); E void FDECL(identify_pack, (int, BOOLEAN_P)); E void NDECL(learn_unseen_invent); E void FDECL(prinv, (const char *, struct obj *, long)); diff --git a/src/apply.c b/src/apply.c index d7b770f4d..07269a358 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2236,16 +2236,19 @@ struct obj **optr; /* Passing FALSE arg here will result in messages displayed */ if (!figurine_location_checks(obj, &cc, FALSE)) return; - You("%s and it transforms.", + You("%s and it %stransforms.", (u.dx || u.dy) ? "set the figurine beside you" : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || is_pool(cc.x, cc.y)) ? "release the figurine" : (u.dz < 0 ? "toss the figurine into the air" - : "set the figurine on the ground")); + : "set the figurine on the ground"), + Blind ? "supposedly " : ""); (void) make_familiar(obj, cc.x, cc.y, FALSE); (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj)); useup(obj); + if (Blind) + map_invisible(cc.x, cc.y); *optr = 0; } diff --git a/src/botl.c b/src/botl.c index a1ea62483..784438a14 100644 --- a/src/botl.c +++ b/src/botl.c @@ -736,7 +736,7 @@ boolean *valsetlist; if (update_all || chg || reset) { idxmax = curr->idxmax; - pc = (idxmax > BL_FLUSH) ? percentage(curr, &blstats[idx][idxmax]) : 0; + pc = (idxmax >= 0) ? percentage(curr, &blstats[idx][idxmax]) : 0; if (!valsetlist[fld]) (void) anything_to_s(curr->val, &curr->a, anytype); @@ -770,8 +770,7 @@ evaluate_and_notify_windowport(valsetlist, idx, idx_p) int idx, idx_p; boolean *valsetlist; { - int i; - boolean updated = FALSE; + int i, updated = 0, notpresent = 0; /* * Now pass the changed values to window port. @@ -781,27 +780,43 @@ boolean *valsetlist; || ((i == BL_EXP) && !flags.showexp) || ((i == BL_TIME) && !flags.time) || ((i == BL_HD) && !Upolyd) - || ((i == BL_XP || i == BL_EXP) && Upolyd)) + || ((i == BL_XP || i == BL_EXP) && Upolyd)) { + notpresent++; continue; + } if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p)) - updated = TRUE; + updated++; } /* - * It is possible to get here, with nothing having been pushed - * to the window port, when none of the info has changed. In that - * case, we need to force a call to status_update() when - * context.botlx is set. The tty port in particular has a problem - * if that isn't done, since it sets context.botlx when a menu or - * text display obliterates the status line. + * Notes: + * 1. It is possible to get here, with nothing having been pushed + * to the window port, when none of the info has changed. + * + * 2. Some window ports are also known to optimize by only drawing + * fields that have changed since the previous update. + * + * In both of those situations, we need to force updates to + * all of the fields when context.botlx is set. The tty port in + * particular has a problem if that isn't done, since the core sets + * context.botlx when a menu or text display obliterates the status + * line. + * + * For those situations, to trigger the full update of every field + * whether changed or not, call status_update() with BL_RESET. + * + * For regular processing and to notify the window port that a + * bot() round has finished and it's time to trigger a flush of + * all buffered changes received thus far but not reflected in + * the display, call status_update() with BL_FLUSH. * - * To work around it, we call status_update() with fictitious - * index of BL_FLUSH (-1). */ - if ((context.botlx && !updated) - || (windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L) + if (context.botlx) + status_update(BL_RESET, (genericptr_t) 0, 0, 0, + NO_COLOR, &cond_hilites[0]); + else if ((windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L) status_update(BL_FLUSH, (genericptr_t) 0, 0, 0, NO_COLOR, &cond_hilites[0]); - + context.botl = context.botlx = 0; update_all = FALSE; } @@ -1936,7 +1951,7 @@ boolean from_configfile; } if (percent) { - if (initblstats[fld].idxmax <= BL_FLUSH) { + if (initblstats[fld].idxmax < 0) { config_error_add("Cannot use percent with '%s'", initblstats[fld].fldname); return FALSE; @@ -2674,7 +2689,7 @@ int fld; int at; int onlybeh = BL_TH_NONE, nopts = 0; - if (fld <= BL_FLUSH || fld >= MAXBLSTATS) + if (fld < 0 || fld >= MAXBLSTATS) return BL_TH_NONE; at = initblstats[fld].anytype; @@ -2717,7 +2732,7 @@ int fld; nopts++; } - if (initblstats[fld].idxmax > BL_FLUSH) { + if (initblstats[fld].idxmax >= 0) { any = zeroany; any.a_int = onlybeh = BL_TH_VAL_PERCENTAGE; add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE, @@ -2849,6 +2864,7 @@ choose_field: fld = origfld; if (fld == BL_FLUSH) { fld = status_hilite_menu_choose_field(); + /* isn't this redundant given what follows? */ if (fld == BL_FLUSH) return FALSE; } diff --git a/src/cmd.c b/src/cmd.c index 3afa198b0..d73d0e60e 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -652,7 +652,6 @@ wiz_identify(VOID_ARGS) it doesn't matter whether the command has been remapped */ if (display_inventory((char *) 0, TRUE) == C('I')) identify_pack(0, FALSE); - /* [TODO? if player picks a specific inventory item, ID it] */ iflags.override_ID = 0; } else pline("Unavailable command '%s'.", diff --git a/src/hack.c b/src/hack.c index 0687c0ef6..cb92b93ad 100644 --- a/src/hack.c +++ b/src/hack.c @@ -2468,16 +2468,14 @@ register boolean newlev; return; } -/* the ',' command */ +/* returns + 1 = cannot pickup, time taken + 0 = cannot pickup, no time taken + -1 = do normal pickup + -2 = loot the monster */ int -dopickup() +pickup_checks() { - int count, tmpcount; - struct trap *traphere = t_at(u.ux, u.uy); - - /* awful kludge to work around parse()'s pre-decrement */ - count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0; - multi = 0; /* always reset */ /* uswallow case added by GAN 01/29/87 */ if (u.uswallow) { if (!u.ustuck->minvent) { @@ -2489,8 +2487,7 @@ dopickup() Blind ? "feel" : "see"); return 1; } else { - tmpcount = -count; - return loot_mon(u.ustuck, &tmpcount, (boolean *) 0); + return -2; /* loot the monster inventory */ } } if (is_pool(u.ux, u.uy)) { @@ -2532,6 +2529,7 @@ dopickup() return 0; } if (!can_reach_floor(TRUE)) { + struct trap *traphere = t_at(u.ux, u.uy); if (traphere && uteetering_at_seen_pit(traphere)) You("cannot reach the bottom of the pit."); else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) @@ -2542,6 +2540,25 @@ dopickup() You("cannot reach the %s.", surface(u.ux, u.uy)); return 0; } + return -1; /* can do normal pickup */ +} + +/* the ',' command */ +int +dopickup(VOID_ARGS) +{ + int count, tmpcount, ret; + + /* awful kludge to work around parse()'s pre-decrement */ + count = (multi || (save_cm && *save_cm == cmd_from_func(dopickup))) ? multi + 1 : 0; + multi = 0; /* always reset */ + + if ((ret = pickup_checks() >= 0)) + return ret; + else if (ret == -2) { + tmpcount = -count; + return loot_mon(u.ustuck, &tmpcount, (boolean *) 0); + } /* else ret == -1 */ return pickup(-count); } diff --git a/src/invent.c b/src/invent.c index 6355a255a..25280839b 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2279,6 +2279,19 @@ int id_limit; } } } +/* count the unidentified items */ +int +count_unidentified(objchn) +struct obj *objchn; +{ + int unid_cnt = 0; + struct obj *obj; + + for (obj = objchn; obj; obj = obj->nobj) + if (not_fully_identified(obj)) + ++unid_cnt; + return unid_cnt; +} /* dialog with user to identify a given number of items; 0 means all */ void @@ -2286,28 +2299,21 @@ identify_pack(id_limit, learning_id) int id_limit; boolean learning_id; /* true if we just read unknown identify scroll */ { - struct obj *obj, *the_obj; - int n, unid_cnt; - - unid_cnt = 0; - the_obj = 0; /* if unid_cnt ends up 1, this will be it */ - for (obj = invent; obj; obj = obj->nobj) - if (not_fully_identified(obj)) - ++unid_cnt, the_obj = obj; + struct obj *obj; + int n, unid_cnt = count_unidentified(invent); if (!unid_cnt) { You("have already identified all %sof your possessions.", learning_id ? "the rest " : ""); } else if (!id_limit || id_limit >= unid_cnt) { /* identify everything */ - if (unid_cnt == 1) { - (void) identify(the_obj); - } else { - /* TODO: use fully_identify_obj and cornline/menu/whatever here - */ - for (obj = invent; obj; obj = obj->nobj) - if (not_fully_identified(obj)) - (void) identify(obj); + /* TODO: use fully_identify_obj and cornline/menu/whatever here */ + for (obj = invent; obj; obj = obj->nobj) { + if (not_fully_identified(obj)) { + (void) identify(obj); + if (unid_cnt == 1) + break; + } } } else { /* identify up to `id_limit' items */ @@ -2491,7 +2497,7 @@ boolean want_reply; long *out_cnt; { static const char not_carrying_anything[] = "Not carrying anything"; - struct obj *otmp; + struct obj *otmp, wizid_fakeobj; char ilet, ret; char *invlet = flags.inv_order; int n, classcount; @@ -2500,6 +2506,7 @@ long *out_cnt; menu_item *selected; unsigned sortflags; Loot *sortedinvent, *srtinv; + boolean wizid = FALSE; if (lets && !*lets) lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */ @@ -2582,22 +2589,33 @@ long *out_cnt; start_menu(win); any = zeroany; if (wizard && iflags.override_ID) { + int unid_cnt; char prompt[QBUFSZ]; - /* C('I') == ^I == default keystroke for wiz_identify; - it is guaranteed not to be in use as an inventory letter - (wiz_identify might be remapped to an ordinary letter, - making iflags.override_ID ambiguous as a return value) */ - any.a_char = C('I'); - /* wiz_identify stuffed the wiz_identify command character (^I) - into iflags.override_ID for our use as an accelerator; - it could be ambiguous as a selector but the only time it - is wanted is in case where no item is being selected */ - Sprintf(prompt, "Debug Identify (%s to permanently identify)", - visctrl(iflags.override_ID)); - add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE, - prompt, MENU_UNSELECTED); - } else if (xtra_choice) { + unid_cnt = count_unidentified(invent); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + "Debug Identify", + MENU_UNSELECTED); + if (!unid_cnt) { + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + "(all items are permanently identified already)", + MENU_UNSELECTED); + } else { + any.a_obj = &wizid_fakeobj; + /* wiz_identify stuffed the wiz_identify command character (^I) + into iflags.override_ID for our use as an accelerator; + it could be ambiguous as a selector but the only time it + is wanted is in case where no item is being selected */ + Sprintf(prompt, + "Select %sthe %d bolded item%s to permanently identify (%s for all)", + (unid_cnt == 1) ? "": "any of ", unid_cnt, + (unid_cnt > 1) ? "s" : "", + visctrl(iflags.override_ID)); + add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE, + prompt, MENU_UNSELECTED); + wizid = TRUE; + } + } else if (xtra_choice) { /* wizard override ID and xtra_choice are mutually exclusive */ if (flags.sortpack) add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, @@ -2621,8 +2639,13 @@ nextclass: MENU_UNSELECTED); classcount++; } - any.a_char = ilet; - add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE, + if (wizid) + any.a_obj = otmp; + else + any.a_char = ilet; + add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, + (wizid && not_fully_identified(otmp)) ? + ATR_BOLD : ATR_NONE, doname(otmp), MENU_UNSELECTED); } } @@ -2655,11 +2678,31 @@ nextclass: } end_menu(win, query && *query ? query : (char *) 0); - n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected); + n = select_menu(win, wizid ? PICK_ANY : + want_reply ? PICK_ONE : PICK_NONE, &selected); if (n > 0) { - ret = selected[0].item.a_char; - if (out_cnt) - *out_cnt = selected[0].count; + if (wizid) { + int i = n; + + ret = '\0'; + while (--i >= 0) { + otmp = selected[i].item.a_obj; + if (otmp == &wizid_fakeobj) { + /* C('I') == ^I == default keystroke for wiz_identify; + it is guaranteed not to be in use as an inventory letter + (wiz_identify might be remapped to an ordinary letter, + making iflags.override_ID ambiguous as a return value) */ + ret = C('I'); + } else { + if (not_fully_identified(otmp)) + (void) identify(otmp); + } + } + } else { + ret = selected[0].item.a_char; + if (out_cnt) + *out_cnt = selected[0].count; + } free((genericptr_t) selected); } else ret = !n ? '\0' : '\033'; /* cancelled */ diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 42dad00c2..5ad7a3dcc 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -66,7 +66,7 @@ struct window_procs tty_procs = { | WC2_SELECTSAVED #endif #if defined(STATUS_HILITES) - | WC2_HILITE_STATUS | WC2_HITPOINTBAR + | WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS #endif | WC2_DARKGRAY), tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event, @@ -3543,6 +3543,8 @@ static int cond_shrinklvl = 0, cond_width_at_shrink = 0; static int enclev = 0, enc_shrinklvl = 0; /* static int dl_shrinklvl = 0; */ static boolean truncation_expected = FALSE; +#define FORCE_RESET TRUE +#define NO_RESET FALSE /* This controls whether to skip fields that aren't * flagged as requiring updating during the current @@ -3552,11 +3554,13 @@ static boolean truncation_expected = FALSE; * for all platforms eventually and the conditional * setting below can be removed. */ -#if defined(UNIX) -static int do_field_opt = 0; +static int do_field_opt = +#if defined(DISABLE_TTY_FIELD_OPT) + 0; #else -static int do_field_opt = 1; + 1; #endif + #endif /* STATUS_HILITES */ /* @@ -3571,7 +3575,7 @@ tty_status_init() int i; for (i = 0; i < MAXBLSTATS; ++i) { - tty_status[NOW][i].idx = -1; + tty_status[NOW][i].idx = BL_FLUSH; tty_status[NOW][i].color = NO_COLOR; /* no color */ tty_status[NOW][i].attr = ATR_NONE; tty_status[NOW][i].x = 0; @@ -3602,7 +3606,11 @@ tty_status_init() * BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, * BL_LEVELDESC, BL_EXP, BL_CONDITION * -- fldindex could also be BL_FLUSH (-1), which is not really - * a field index, but is a special trigger to tell the + * a field index, but is a special trigger to tell the + * windowport that it should output all changes received + * to this point. It marks the end of a bot() cycle. + * -- fldindex could also be BL_RESET (-3), which is not really + * a field index, but is a special advisory to to tell the * windowport that it should redisplay all its status fields, * even if no changes have been presented to it. * -- ptr is usually a "char *", unless fldindex is BL_CONDITION. @@ -3655,9 +3663,9 @@ unsigned long *colormasks; char *text = (char *) ptr; char *lastchar = (char *) 0; char *fval = (char *) 0; - boolean force_update = FALSE; + boolean reset_state = NO_RESET; - if (fldidx != BL_FLUSH && !status_activefields[fldidx]) + if ((fldidx >= 0 && fldidx < MAXBLSTATS) && !status_activefields[fldidx]) return; #ifndef TEXTCOLOR @@ -3665,9 +3673,13 @@ unsigned long *colormasks; #endif switch (fldidx) { + case BL_RESET: + reset_state = FORCE_RESET; + /* FALLTHRU */ case BL_FLUSH: - force_update = TRUE; - break; + if (make_things_fit(reset_state) || truncation_expected) + render_status(); + return; case BL_CONDITION: tty_status[NOW][fldidx].idx = fldidx; tty_condition_bits = *condptr; @@ -3691,7 +3703,8 @@ unsigned long *colormasks; /* The core botl engine sends a single blank to the window port for carrying-capacity when its unused. Let's suppress that */ - if (tty_status[NOW][fldidx].lth == 1 && status_vals[fldidx][0] == ' ') { + if (fldidx >= 0 && fldidx < MAXBLSTATS && + tty_status[NOW][fldidx].lth == 1 && status_vals[fldidx][0] == ' ') { status_vals[fldidx][0] = '\0'; tty_status[NOW][fldidx].lth = 0; } @@ -3704,6 +3717,10 @@ unsigned long *colormasks; hpbar_percent = percent; hpbar_color = (color & 0x00FF); } + if (iflags.wc2_hitpointbar && (tty_procs.wincap2 & WC2_FLUSH_STATUS) != 0L) { + tty_status[NOW][BL_TITLE].color = hpbar_color; + tty_status[NOW][BL_TITLE].dirty = TRUE; + } break; case BL_LEVELDESC: case BL_HUNGER: @@ -3737,8 +3754,7 @@ unsigned long *colormasks; } break; } - if (make_things_fit(force_update) || truncation_expected) - render_status(); + /* 3.6.2 we only render on BL_FLUSH (or BL_RESET) */ return; } @@ -3802,7 +3818,7 @@ boolean forcefields; int *topsz, *bottomsz; { int c, i, row, col, trackx, idx; - boolean valid = TRUE, matchprev = FALSE, update_right; + boolean valid = TRUE, matchprev = FALSE, update_right, disregard; if (!windowdata_init && !check_windowdata()) return FALSE; @@ -3830,25 +3846,32 @@ int *topsz, *bottomsz; * Check values against those already on the dislay. * - Is the additional processing time for this worth it? */ - matchprev = FALSE; - if (do_field_opt && tty_status[NOW][idx].dirty) { - /* compare values */ - const char *ob, *nb; /* old byte, new byte */ + if (do_field_opt) { + matchprev = FALSE; + disregard = (tty_status[NOW][idx].lth == 0); + if (do_field_opt && !disregard + && tty_status[NOW][idx].dirty) { + /* compare values */ + const char *ob, *nb; /* old byte, new byte */ - c = col - 1; - ob = &wins[WIN_STATUS]->data[row][c]; - nb = status_vals[idx]; - while (*nb && c < wins[WIN_STATUS]->cols) { - if (*nb != *ob) - break; - nb++; - ob++; - c++; + c = col - 1; + ob = &wins[WIN_STATUS]->data[row][c]; + nb = status_vals[idx]; + while (*nb && c < wins[WIN_STATUS]->cols) { + if (*nb != *ob) + break; + nb++; + ob++; + c++; + } + if (!*nb && c > col - 1) + matchprev = TRUE; } - if (!*nb && c > col - 1) - matchprev = TRUE; + } else { + matchprev = FALSE; } } + /* * With STATUS_HILITES, it is possible that the color * needs to change even if the text is the same, so @@ -3858,7 +3881,8 @@ int *topsz, *bottomsz; * After the field has been updated, render_status() * will also clear .redraw and .dirty. */ - if (forcefields || update_right || !matchprev + if (forcefields || update_right + || (!matchprev && tty_status[NOW][idx].dirty && !disregard) || tty_status[NOW][idx].color != tty_status[BEFORE][idx].color || tty_status[NOW][idx].attr != tty_status[BEFORE][idx].attr) tty_status[NOW][idx].redraw = TRUE; diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 8f3e1ae1f..fb9ad0a94 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -2857,10 +2857,14 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percent, int color, u BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC, BL_EXP, BL_CONDITION - -- fldindex could also be BL_FLUSH (-1), which is not really - a field index, but is a special trigger to tell the - windowport that it should redisplay all its status fields, - even if no changes have been presented to it. + -- fldindex could also be BL_FLUSH, which is not really + a field index, but is a special trigger to tell the + windowport that it should output all changes received + to this point. It marks the end of a bot() cycle. + -- fldindex could also be BL_RESET, which is not really + a field index, but is a special advisory to to tell the + windowport that it should redisplay all its status fields, + even if no changes have been presented to it. -- ptr is usually a "char *", unless fldindex is BL_CONDITION. If fldindex is BL_CONDITION, then ptr is a long value with any or none of the following bits set (from botl.h): @@ -2898,7 +2902,7 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, colormasks); - if (idx != BL_FLUSH) { + if (idx != BL_FLUSH && idx != BL_RESET) { if (!_status_activefields[idx]) return; _status_percents[idx] = percent;