diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 051f61299..956ba2aa1 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,4 +1,4 @@ -.\" $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.301 $ $NHDT-Date: 1553480404 2019/03/25 02:20:04 $ +.\" $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.302 $ $NHDT-Date: 1553858473 2019/03/29 11:21:13 $ .\" .\" This is an excerpt from the 'roff' man page from the 'groff' package. .\" NetHack's Guidebook.mn currently does *not* adhere to these guidelines. @@ -3657,7 +3657,7 @@ up (default yes). .lp statuslines Number of lines for traditional below-the-map status display. Acceptable values are 2 and 3 (default is 2). -Curses interface only. +Curses and tty interfaces only. .lp "term_cols\ \ \fIand\fP" .lp term_rows Curses interface only. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index fa1a9872a..151bed238 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -4057,7 +4057,7 @@ it starts up (default yes). \item[\ib{statuslines}] Number of lines for traditional below-the-map status display. Acceptable values are 2 and 3 (default is 2). -Curses interface only. +Curses and tty interfaces only. %.lp \item[\ib{term\verb+_+cols}\ \ {\it and}]" %.lp diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 66de6f54d..72cb9856f 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.286 $ $NHDT-Date: 1553787633 2019/03/28 15:40:33 $ +$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.287 $ $NHDT-Date: 1553858472 2019/03/29 11:21:12 $ 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, @@ -653,6 +653,8 @@ curses: status display substantially revamped for both horizontal (via 'align_status:bottom' or 'top') and vertical (via 'align_status:left' or 'right'); 3-line horizontal layout (via 'statuslines:3') added curses: support msg_window:full; default is still msg_window:reversed +tty: support statuslines:3 and dynamically switching between 2 and 3 with 'O' + (requires a display with at least 25 lines or that CLIPPING be enabled) NetHack Community Patches (or Variation) Included diff --git a/include/wintty.h b/include/wintty.h index f7e5b0611..1a609de2a 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 wintty.h $NHDT-Date: 1549327485 2019/02/05 00:44:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.32 $ */ +/* NetHack 3.6 wintty.h $NHDT-Date: 1553858470 2019/03/29 11:21:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.33 $ */ /* Copyright (c) David Cohrs, 1991,1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -79,7 +79,7 @@ struct tty_status_fields { boolean valid; boolean dirty; boolean redraw; - boolean last_on_row; + boolean _not_used; /* was 'last_in_row' */ }; #endif @@ -151,6 +151,7 @@ E void NDECL(cl_eos); * a color or whatever. wintty.c should concern itself with WHERE to put * stuff in a window. */ +E int FDECL(term_attr_fixup, (int)); E void FDECL(term_start_attr, (int attr)); E void FDECL(term_end_attr, (int attr)); E void NDECL(term_start_raw_bold); @@ -182,6 +183,7 @@ E void FDECL(win_tty_init, (int)); /* external declarations */ E void FDECL(tty_init_nhwindows, (int *, char **)); +E void FDECL(tty_preference_update, (const char *)); E void NDECL(tty_player_selection); E void NDECL(tty_askname); E void NDECL(tty_get_nh_event); diff --git a/src/options.c b/src/options.c index f90cef3bd..c4471cf61 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1553480404 2019/03/25 02:20:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.360 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1553858470 2019/03/29 11:21:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.361 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -385,20 +385,23 @@ static struct Comp_Opt { #ifdef MSDOS { "soundcard", "type of sound card to use", 20, SET_IN_FILE }, #endif -#ifdef STATUS_HILITES { "statushilites", +#ifdef STATUS_HILITES "0=no status highlighting, N=show highlights for N turns", - 20, SET_IN_GAME }, + 20, SET_IN_GAME #else - { "statushilites", "highlight control", 20, SET_IN_FILE }, + "highlight control", 20, SET_IN_FILE #endif -#ifdef CURSES_GRAPHICS + }, { "statuslines", +#ifdef CURSES_GRAPHICS "2 or 3 lines for horizonal (bottom or top) status display", - 20, SET_IN_GAME }, /*WC2*/ + 20, SET_IN_GAME #else - { "statuslines", "2 or 3 lines for status display", 20, SET_IN_FILE }, + "2 or 3 lines for status display", + 20, SET_IN_FILE #endif + }, /*WC2*/ { "symset", "load a set of display symbols from the symbols file", 70, SET_IN_GAME }, { "roguesymset", @@ -3703,6 +3706,7 @@ boolean tinitial, tfrom_file; } return retval; } +#endif /* CURSES_GRAPHICS */ /* WINCAP2 * statuslines:n */ @@ -3728,7 +3732,6 @@ boolean tinitial, tfrom_file; } return retval; } -#endif /* CURSES_GRAPHICS */ /* menustyle:traditional or combination or full or partial */ fullname = "menustyle"; @@ -5739,8 +5742,9 @@ char *buf; iflags.hilite_delta, iflags.hilite_delta); #endif } else if (!strcmp(optname,"statuslines")) { - Strcpy(buf, (WINDOWPORT("curses") - && iflags.wc2_statuslines < 3) ? "2" : "3"); + if (wc2_supported(optname)) + Strcpy(buf, (iflags.wc2_statuslines < 3) ? "2" : "3"); + /* else default to "unknown" */ } else if (!strcmp(optname, "suppress_alert")) { if (flags.suppress_alert == 0L) Strcpy(buf, none); diff --git a/win/tty/termcap.c b/win/tty/termcap.c index c373df04c..ead39d228 100644 --- a/win/tty/termcap.c +++ b/win/tty/termcap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 termcap.c $NHDT-Date: 1456907853 2016/03/02 08:37:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */ +/* NetHack 3.6 termcap.c $NHDT-Date: 1553858473 2019/03/29 11:21:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.29 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1206,12 +1206,37 @@ int n; return nulstr; } +/* suppress nonfunctional highlights so render_status() might be able to + optimize more; keep this in sync with s_atr2str() */ +int +term_attr_fixup(msk) +int msk; +{ + /* underline is converted to bold if its start sequence isn't available */ + if ((msk & (1 << ATR_ULINE)) && !nh_US) { + msk |= (1 << ATR_BOLD); + msk &= ~(1 << ATR_ULINE); + } + /* blink is converted to bold unconditionally [why?] */ + if (msk & (1 << ATR_BLINK)) { + msk |= (1 << ATR_BOLD); + msk &= ~(1 << ATR_BLINK); + } + /* dim is ignored */ + if (msk & (1 << ATR_DIM)) + msk &= ~(1 << ATR_DIM); + return msk; +} + void term_start_attr(attr) int attr; { if (attr) { - xputs(s_atr2str(attr)); + const char *astr = s_atr2str(attr); + + if (*astr) + xputs(s_atr2str(attr)); } } @@ -1220,7 +1245,10 @@ term_end_attr(attr) int attr; { if (attr) { - xputs(e_atr2str(attr)); + const char *astr = e_atr2str(attr); + + if (*astr) + xputs(e_atr2str(attr)); } } @@ -1248,7 +1276,8 @@ void term_start_color(color) int color; { - xputs(hilites[color]); + if (color < CLR_MAX) + xputs(hilites[color]); } /* not to be confused with has_colors() in unixtty.c */ diff --git a/win/tty/wintty.c b/win/tty/wintty.c index b7ad2bf5b..fe06b8180 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wintty.c $NHDT-Date: 1553716531 2019/03/27 19:55:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.198 $ */ +/* NetHack 3.6 wintty.c $NHDT-Date: 1553858474 2019/03/29 11:21:14 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.199 $ */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -96,7 +96,7 @@ struct window_procs tty_procs = { | WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_RESET_STATUS #endif - | WC2_DARKGRAY | WC2_SUPPRESS_HIST), + | WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_STATUSLINES), tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event, tty_exit_nhwindows, tty_suspend_nhwindows, tty_resume_nhwindows, tty_create_nhwindow, tty_clear_nhwindow, tty_display_nhwindow, @@ -123,11 +123,7 @@ struct window_procs tty_procs = { /* other defs that really should go away (they're tty specific) */ tty_start_screen, tty_end_screen, genl_outrip, -#if defined(WIN32) - nttty_preference_update, -#else - genl_preference_update, -#endif + tty_preference_update, tty_getmsghistory, tty_putmsghistory, tty_status_init, genl_status_finish, tty_status_enablefield, @@ -179,8 +175,10 @@ static const char to_continue[] = "to continue"; #else STATIC_DCL void NDECL(getret); #endif -STATIC_DCL void FDECL(erase_menu_or_text, - (winid, struct WinDesc *, BOOLEAN_P)); +STATIC_DCL void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */ +STATIC_DCL void NDECL(new_status_window); +STATIC_DCL void FDECL(erase_menu_or_text, (winid, struct WinDesc *, + BOOLEAN_P)); STATIC_DCL void FDECL(free_window_info, (struct WinDesc *, BOOLEAN_P)); STATIC_DCL void FDECL(dmore, (struct WinDesc *, const char *)); STATIC_DCL void FDECL(set_item_state, (winid, int, tty_menu_item *)); @@ -198,23 +196,20 @@ STATIC_DCL void FDECL(process_text_window, (winid, struct WinDesc *)); STATIC_DCL tty_menu_item *FDECL(reverse, (tty_menu_item *)); STATIC_DCL const char *FDECL(compress_str, (const char *)); STATIC_DCL void FDECL(tty_putsym, (winid, int, int, CHAR_P)); -STATIC_DCL void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */ STATIC_DCL void FDECL(setup_rolemenu, (winid, BOOLEAN_P, int, int, int)); STATIC_DCL void FDECL(setup_racemenu, (winid, BOOLEAN_P, int, int, int)); STATIC_DCL void FDECL(setup_gendmenu, (winid, BOOLEAN_P, int, int, int)); STATIC_DCL void FDECL(setup_algnmenu, (winid, BOOLEAN_P, int, int, int)); STATIC_DCL boolean NDECL(reset_role_filtering); #ifdef STATUS_HILITES -STATIC_DCL boolean FDECL(check_fields, (BOOLEAN_P, int *, int *)); +STATIC_DCL boolean FDECL(check_fields, (BOOLEAN_P, int *)); STATIC_DCL void NDECL(render_status); -STATIC_DCL void FDECL(tty_putstatusfield, (struct tty_status_fields *, - const char *, int, int)); +STATIC_DCL void FDECL(tty_putstatusfield, (const char *, int, int)); STATIC_DCL boolean NDECL(check_windowdata); STATIC_DCL int NDECL(condition_size); STATIC_DCL int FDECL(make_things_fit, (BOOLEAN_P)); STATIC_DCL void FDECL(shrink_enc, (int)); STATIC_DCL void FDECL(shrink_dlvl, (int)); -STATIC_DCL void NDECL(do_setlast); #endif /* @@ -322,19 +317,8 @@ int sig_unused UNUSED; cw = wins[WIN_MESSAGE]; cw->curx = cw->cury = 0; - tty_destroy_nhwindow(WIN_STATUS); - WIN_STATUS = tty_create_nhwindow(NHW_STATUS); - + new_status_window(); if (u.ux) { -#ifdef CLIPPING - if (CO < COLNO || LI < ROWNO + 3) { - setclipped(); - tty_cliparound(u.ux, u.uy); - } else { - clipping = FALSE; - clipx = clipy = 0; - } -#endif i = ttyDisplay->toplin; ttyDisplay->toplin = 0; docrt(); @@ -359,6 +343,41 @@ int sig_unused UNUSED; } #endif +/* destroy and recreate status window; extracted from winch_handler() + and augmented for use by tty_preference_update() */ +STATIC_OVL void +new_status_window() +{ + if (WIN_STATUS != WIN_ERR) { + /* if it's shrinking, clear it before destroying so that + dropped portion won't show anything that's now becoming stale */ + if (wins[WIN_STATUS]->maxrow > iflags.wc2_statuslines) + tty_clear_nhwindow(WIN_STATUS); + + tty_destroy_nhwindow(WIN_STATUS), WIN_STATUS = WIN_ERR; + } + /* frees some status tracking data */ + genl_status_finish(); + /* creates status window and allocates tracking data */ + tty_status_init(); + tty_clear_nhwindow(WIN_STATUS); /* does some init, sets context.botlx */ +#ifdef STATUS_HILITES + status_initialize(REASSESS_ONLY); +#endif + +#ifdef CLIPPING + if (u.ux) { + if (LI < 1 + ROWNO + iflags.wc2_statuslines) { + setclipped(); + tty_cliparound(u.ux, u.uy); + } else { + clipping = FALSE; + clipx = clipy = 0; + } + } +#endif +} + /*ARGSUSED*/ void tty_init_nhwindows(argcp, argv) @@ -367,14 +386,17 @@ char **argv UNUSED; { int wid, hgt, i; -/* - * Remember tty modes, to be restored on exit. - * - * gettty() must be called before tty_startup() - * due to ordering of LI/CO settings - * tty_startup() must be called before initoptions() - * due to ordering of graphics settings - */ + /* options aren't processed yet so wc2_statuslines might be 0; + make sure that it has a reasonable value during tty setup */ + iflags.wc2_statuslines = (iflags.wc2_statuslines < 3) ? 2 : 3; + /* + * Remember tty modes, to be restored on exit. + * + * gettty() must be called before tty_startup() + * due to ordering of LI/CO settings + * tty_startup() must be called before initoptions() + * due to ordering of graphics settings + */ #if defined(UNIX) || defined(VMS) setbuf(stdout, obuf); #endif @@ -414,6 +436,31 @@ char **argv UNUSED; tty_putstr(BASE_WINDOW, 0, copyright_banner_line(i)); tty_putstr(BASE_WINDOW, 0, ""); tty_display_nhwindow(BASE_WINDOW, FALSE); + + /* 'statuslines' defaults to SET_IN_FILE, allowed but invisible; + make it dynamically settable if feasible, otherwise visible */ + if (tty_procs.wincap2 & WC2_STATUSLINES) + set_wc2_option_mod_status(WC2_STATUSLINES, +#ifndef CLIPPING + (LI < 1 + ROWNO + 2) ? DISP_IN_GAME : +#endif + SET_IN_GAME); +} + +void +tty_preference_update(pref) +const char *pref; +{ + if (!strcmp(pref, "statuslines") && iflags.window_inited) { + new_status_window(); + } + +#if defined(WIN32) + nttty_preference_update(pref); +#else + genl_preference_update(pref); +#endif + return; } /* try to reduce clutter in the code below... */ @@ -1367,7 +1414,7 @@ tty_create_nhwindow(type) int type; { struct WinDesc *newwin; - int i; + int i, rowoffset; int newid; if (maxwin == MAXWIN) @@ -1402,15 +1449,22 @@ int type; newwin->maxcol = newwin->cols = 0; break; case NHW_STATUS: - /* status window, 2 lines long, full width, bottom of screen */ + /* status window, 2 or 3 lines long, full width, bottom of screen */ + if (iflags.wc2_statuslines < 2 +#ifndef CLIPPING + || (LI < 1 + ROWNO + 3) +#endif + || iflags.wc2_statuslines > 3) + iflags.wc2_statuslines = 2; newwin->offx = 0; + rowoffset = ttyDisplay->rows - iflags.wc2_statuslines; #if defined(USE_TILES) && defined(MSDOS) if (iflags.grmode) { - newwin->offy = ttyDisplay->rows - 2; + newwin->offy = rowoffset; } else #endif - newwin->offy = min((int) ttyDisplay->rows - 2, ROWNO + 1); - newwin->rows = newwin->maxrow = 2; + newwin->offy = min(rowoffset, ROWNO + 1); + newwin->rows = newwin->maxrow = iflags.wc2_statuslines; newwin->cols = newwin->maxcol = ttyDisplay->cols; break; case NHW_MAP: @@ -1424,9 +1478,8 @@ int type; break; case NHW_MENU: case NHW_TEXT: - /* inventory/menu window, variable length, full width, top of screen - */ - /* help window, the same, different semantics for display, etc */ + /* inventory/menu window, variable length, full width, top of screen; + help window, the same, different semantics for display, etc */ newwin->offx = newwin->offy = 0; newwin->rows = 0; newwin->cols = ttyDisplay->cols; @@ -1449,18 +1502,15 @@ int type; } if (newwin->maxrow) { - newwin->data = - (char **) alloc(sizeof(char *) * (unsigned) newwin->maxrow); - newwin->datlen = - (short *) alloc(sizeof(short) * (unsigned) newwin->maxrow); - if (newwin->maxcol) { - /* WIN_STATUS */ - for (i = 0; i < newwin->maxrow; i++) { + newwin->data = (char **) alloc( + (unsigned) (newwin->maxrow * sizeof (char *))); + newwin->datlen = (short *) alloc( + (unsigned) (newwin->maxrow * sizeof (short))); + for (i = 0; i < newwin->maxrow; i++) { + if (newwin->maxcol) { /* WIN_STATUS */ newwin->data[i] = (char *) alloc((unsigned) newwin->maxcol); newwin->datlen[i] = (short) newwin->maxcol; - } - } else { - for (i = 0; i < newwin->maxrow; i++) { + } else { newwin->data[i] = (char *) 0; newwin->datlen[i] = 0; } @@ -1547,6 +1597,7 @@ void tty_clear_nhwindow(window) winid window; { + int i, j, m, n; register struct WinDesc *cw = 0; HUPSKIP(); @@ -1567,10 +1618,18 @@ winid window; } break; case NHW_STATUS: - tty_curs(window, 1, 0); - cl_end(); - tty_curs(window, 1, 1); - cl_end(); + m = cw->maxrow; + n = cw->cols; + for (i = 0; i < m; ++i) { + tty_curs(window, 1, i); + cl_end(); + + for (j = 0; j < n - 1; ++j) + cw->data[i][j] = ' '; + cw->data[i][n - 1] = '\0'; + /*finalx[i][NOW] = finalx[i][BEFORE] = 0;*/ + } + context.botlx = 1; break; case NHW_MAP: /* cheap -- clear the whole thing and tell nethack to redraw botl */ @@ -1578,6 +1637,8 @@ winid window; /*FALLTHRU*/ case NHW_BASE: clear_screen(); + /*for (i = 0; i < cw->maxrow; ++i) */ + /* finalx[i][NOW] = finalx[i][BEFORE] = 0;*/ break; case NHW_MENU: case NHW_TEXT: @@ -2612,7 +2673,7 @@ const char *str; case NHW_STATUS: ob = &cw->data[cw->cury][j = cw->curx]; if (context.botlx) - *ob = 0; + *ob = '\0'; if (!cw->cury && (int) strlen(str) >= CO) { /* the characters before "St:" are unnecessary */ nb = index(str, ':'); @@ -2637,7 +2698,7 @@ const char *str; (void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1); cw->data[cw->cury][cw->cols - 1] = '\0'; /* null terminate */ - cw->cury = (cw->cury + 1) % 2; + cw->cury = (cw->cury + 1) % cw->maxrow; cw->curx = 0; break; #endif /* STATUS_HILITES */ @@ -2950,7 +3011,7 @@ const char *prompt; /* prompt to for menu */ free((genericptr_t) cw->plist); cw->plist_size = cw->npages + 1; cw->plist = (tty_menu_item **) alloc(cw->plist_size - * sizeof(tty_menu_item *)); + * sizeof (tty_menu_item *)); } cw->cols = 0; /* cols is set when the win is initialized... (why?) */ @@ -3247,7 +3308,7 @@ setclipped() clipping = TRUE; clipx = clipy = 0; clipxmax = CO; - clipymax = LI - 3; + clipymax = LI - 1 - iflags.wc2_statuslines; } void @@ -3269,10 +3330,10 @@ int x, y; } if (y < clipy + 2) { clipy = max(0, y - (clipymax - clipy) / 2); - clipymax = clipy + (LI - 3); + clipymax = clipy + (LI - 1 - iflags.wc2_statuslines); } else if (y > clipymax - 2) { clipymax = min(ROWNO, clipymax + (clipymax - clipy) / 2); - clipy = clipymax - (LI - 3); + clipy = clipymax - (LI - 1 - iflags.wc2_statuslines); } if (clipx != oldx || clipy != oldy) { if (on_level(&u.uz0, &u.uz) && !restoring) @@ -3582,14 +3643,6 @@ extern char *status_vals[MAXBLSTATS]; extern boolean status_activefields[MAXBLSTATS]; extern winid WIN_STATUS; -const char *fieldnames[] = { - "title", "strength", "dexterity", "constitution", "intelligence", - "wisdom", "charisma", "alignment", "score", "carrying-capacity", - "gold", "power", "power-max", "experience-level", "armor-class", - "HD", "time", "hunger", "hitpoints", "hitpoints-max", - "dungeon-level", "experience", "condition", -}; - #ifdef STATUS_HILITES #ifdef TEXTCOLOR STATIC_DCL int FDECL(condcolor, (long, unsigned long *)); @@ -3597,10 +3650,7 @@ STATIC_DCL int FDECL(condcolor, (long, unsigned long *)); STATIC_DCL int FDECL(condattr, (long, unsigned long *)); static unsigned long *tty_colormasks; static long tty_condition_bits; -int cond_disp_width[2]; /* 2: current and previous */ -static struct tty_status_fields - tty_status[2][MAXBLSTATS]; /* 2: first index is for current - and previous */ +static struct tty_status_fields tty_status[2][MAXBLSTATS]; /* 2: NOW,BEFORE */ static int hpbar_percent, hpbar_color; static struct condition_t { long mask; @@ -3626,21 +3676,35 @@ static const char *encvals[3][6] = { { "", "Burden", "Stress", "Strain", "Overtax", "Overload" }, { "", "Brd", "Strs", "Strn", "Ovtx", "Ovld" } }; +#define blPAD BL_FLUSH #define MAX_PER_ROW 15 -static enum statusfields fieldorder[2][MAX_PER_ROW] = { /* 2: 2 status lines */ +/* 2 or 3 status lines */ +static const enum statusfields + twolineorder[3][MAX_PER_ROW] = { { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN, - BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, - BL_FLUSH }, + BL_SCORE, BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD }, { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER, - BL_CAP, BL_CONDITION, BL_FLUSH } + BL_CAP, BL_CONDITION, BL_FLUSH }, + /* third row of array isn't used for twolineorder */ + { BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, + blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD } +}, + /* Align moved from 1 to 2, Leveldesc+Time+Condition moved from 2 to 3 */ + threelineorder[3][MAX_PER_ROW] = { + { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, + BL_SCORE, BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD }, + { BL_ALIGN, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, + BL_AC, BL_XP, BL_EXP, BL_HD, BL_HUNGER, + BL_CAP, BL_FLUSH, blPAD, blPAD }, + { BL_LEVELDESC, BL_TIME, BL_CONDITION, BL_FLUSH, blPAD, blPAD, + blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD } }; +static const enum statusfields (*fieldorder)[3][MAX_PER_ROW]; -static int last_on_row[2]; /* [rows] */ -static int finalx[2][2]; /* [rows][NOW or BEFORE] */ -static boolean setlast = FALSE; +static int finalx[3][2]; /* [rows][NOW or BEFORE] */ static boolean windowdata_init = FALSE; -static int cond_shrinklvl = 0, cond_width_at_shrink = 0; +static int cond_shrinklvl = 0; static int enclev = 0, enc_shrinklvl = 0; /* static int dl_shrinklvl = 0; */ static boolean truncation_expected = FALSE; @@ -3673,18 +3737,19 @@ void tty_status_init() { #ifdef STATUS_HILITES - int i; + int i, num_rows; + + num_rows = (iflags.wc2_statuslines < 3) ? 2 : 3; + fieldorder = (num_rows != 3) ? &twolineorder : &threelineorder; for (i = 0; i < MAXBLSTATS; ++i) { 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; - tty_status[NOW][i].y = 0; + tty_status[NOW][i].x = tty_status[NOW][i].y = 0; tty_status[NOW][i].valid = FALSE; tty_status[NOW][i].dirty = FALSE; tty_status[NOW][i].redraw = FALSE; - tty_status[NOW][i].last_on_row = FALSE; tty_status[BEFORE][i] = tty_status[NOW][i]; } tty_condition_bits = 0L; @@ -3703,10 +3768,6 @@ const char *fmt; boolean enable; { genl_status_enablefield(fieldidx, nm, fmt, enable); -#ifdef STATUS_HILITES - /* force re-evaluation of last field on the row */ - setlast = FALSE; -#endif } #ifdef STATUS_HILITES @@ -3774,10 +3835,11 @@ int fldidx, chg UNUSED, percent, color; genericptr_t ptr; unsigned long *colormasks; { - int i; + int i, attrmask; long *condptr = (long *) ptr; char *text = (char *) ptr; - char *fval, *lastchar, *p; + char goldbuf[40], *fval, *lastchar, *p; + const char *fmt; boolean reset_state = NO_RESET; if ((fldidx < BL_RESET) || (fldidx >= MAXBLSTATS)) @@ -3786,13 +3848,6 @@ unsigned long *colormasks; if ((fldidx >= 0 && fldidx < MAXBLSTATS) && !status_activefields[fldidx]) return; - if (!setlast) - do_setlast(); - -#ifndef TEXTCOLOR - color = (color & ~0x00FF) | NO_COLOR; -#endif - switch (fldidx) { case BL_RESET: reset_state = FORCE_RESET; @@ -3809,13 +3864,28 @@ unsigned long *colormasks; tty_status[NOW][fldidx].dirty = TRUE; truncation_expected = FALSE; break; + case BL_GOLD: + text = decode_mixed(goldbuf, text); + /*FALLTHRU*/ default: + attrmask = (color >> 8) & 0x00FF; +#ifndef TEXTCOLOR + color = NO_COLOR; +#endif + fmt = status_fieldfmt[fldidx]; + if (!fmt) + fmt = "%s"; + /* should be checking for first enabled field here rather than + just first field, but 'fieldorder' doesn't start any rows + with fields which can be disabled so [any_row][0] suffices */ + if (*fmt == ' ' && (fldidx == (*fieldorder)[0][0] + || fldidx == (*fieldorder)[1][0] + || fldidx == (*fieldorder)[2][0])) + ++fmt; /* skip leading space for first field on line */ + Sprintf(status_vals[fldidx], fmt, text); tty_status[NOW][fldidx].idx = fldidx; - Sprintf(status_vals[fldidx], - status_fieldfmt[fldidx] ? status_fieldfmt[fldidx] : "%s", - text); tty_status[NOW][fldidx].color = (color & 0x00FF); - tty_status[NOW][fldidx].attr = ((color >> 8) & 0x00FF); + tty_status[NOW][fldidx].attr = term_attr_fixup(attrmask); tty_status[NOW][fldidx].lth = strlen(status_vals[fldidx]); tty_status[NOW][fldidx].valid = TRUE; tty_status[NOW][fldidx].dirty = TRUE; @@ -3867,11 +3937,14 @@ unsigned long *colormasks; break; case BL_CAP: fval = status_vals[fldidx]; - if (fval) { + enclev = 0; + if (*fval) { + /* TODO: replace this with a callback to the core to + retrieve the cap index directly */ if (*fval == ' ') fval++; - for (i = 0; i < SIZE(encvals); ++i) { - if (!strcmp(encvals[enc_shrinklvl][i], fval)) { + for (i = 0; i < SIZE(encvals[0]); ++i) { + if (!strcmp(encvals[0][i], fval)) { enclev = i; break; /* for */ } @@ -3883,40 +3956,26 @@ unsigned long *colormasks; return; } -void -do_setlast() -{ - int i, row, fld; - - setlast = TRUE; - for (row = 0; row < 2; ++row) - for (i = MAX_PER_ROW - 1; i > 0; --i) { - fld = fieldorder[row][i]; - - if (fld == BL_FLUSH || !status_activefields[fld]) - continue; - - last_on_row[row] = fld; - break; - } -} - STATIC_OVL int make_things_fit(force_update) boolean force_update; { - int trycnt, fitting = 0, condsz = 0, requirement = 0; - int rowsz[2], otheroptions = 0; - boolean check = FALSE; + int trycnt, fitting = 0, condsz, requirement; + int rowsz[3], num_rows, condrow, otheroptions = 0; + num_rows = (iflags.wc2_statuslines < 3) ? 2 : 3; + condrow = num_rows - 1; + cond_shrinklvl = 0; condsz = condition_size(); for (trycnt = 0; trycnt < 6 && !fitting; ++trycnt) { - check = check_fields(force_update, &rowsz[0], &rowsz[1]); - if (!check) + /* FIXME: this remeasures each line every time even though it + is only attempting to shrink one of them and the other one + (or two) remains the same */ + if (!check_fields(force_update, rowsz)) return 0; - requirement = rowsz[1]; - if (requirement < wins[WIN_STATUS]->cols - 1) { + requirement = rowsz[condrow] - 1; + if (requirement <= wins[WIN_STATUS]->cols - 1) { fitting = requirement; break; /* we're good */ } @@ -3924,7 +3983,6 @@ boolean force_update; if (cond_shrinklvl < trycnt + 1) { cond_shrinklvl = trycnt + 1; condsz = condition_size(); - cond_width_at_shrink = cond_disp_width[NOW]; } continue; } @@ -3932,9 +3990,11 @@ boolean force_update; /* We've exhausted the condition identifiers shrinkage, * so let's try something other things... */ - if (otheroptions == 0 || otheroptions == 1) { - /* try shrinking the encumbrance word */ - shrink_enc(otheroptions + 1); + if (otheroptions < 2) { + /* try shrinking the encumbrance word, but + only when it's on the same line as conditions */ + if (num_rows == 2) + shrink_enc(otheroptions + 1); otheroptions++; } else if (otheroptions == 2) { shrink_dlvl(1); @@ -3956,23 +4016,23 @@ boolean force_update; * This is now done at an individual field case-by-case level. */ boolean -check_fields(forcefields, topsz, bottomsz) +check_fields(forcefields, sz) boolean forcefields; -int *topsz, *bottomsz; +int sz[3]; { - int c, i, row, col, trackx, idx; - boolean valid = TRUE, matchprev = FALSE, update_right, disregard = FALSE; + int c, i, row, col, num_rows, idx; + boolean valid = TRUE, matchprev, update_right; if (!windowdata_init && !check_windowdata()) return FALSE; - for (row = 0; row < 2; ++row) { + num_rows = (iflags.wc2_statuslines < 3) ? 2 : 3; + + for (row = 0; row < num_rows; ++row) { + sz[row] = 0; col = 1; - trackx = 1; update_right = FALSE; - idx = -1; - for (i = 0; fieldorder[row][i] != BL_FLUSH; ++i) { - idx = fieldorder[row][i]; + for (i = 0; (idx = (*fieldorder)[row][i]) != BL_FLUSH; ++i) { if (!status_activefields[idx]) continue; if (!tty_status[NOW][idx].valid) @@ -3983,109 +4043,98 @@ int *topsz, *bottomsz; /* On a change to the field length, everything further to the right must be updated as well */ - if (tty_status[NOW][idx].lth != tty_status[BEFORE][idx].lth) + if (tty_status[NOW][idx].lth != tty_status[BEFORE][idx].lth + || (idx == BL_CONDITION + && tty_status[NOW][idx].x != tty_status[BEFORE][idx].x)) update_right = TRUE; - if (idx == last_on_row[row]) - tty_status[NOW][idx].last_on_row = TRUE; - - if (!update_right && !forcefields) { + matchprev = FALSE; /* assume failure */ + if (valid && !update_right && !forcefields) { /* - * Check values against those already on the dislay. + * Check values against those already on the display. * - Is the additional processing time for this worth it? */ - if (do_field_opt) { - matchprev = FALSE; - disregard = (tty_status[NOW][idx].lth == 0); - if (do_field_opt && !disregard - && tty_status[NOW][idx].dirty) { + if (do_field_opt + && (tty_status[NOW][idx].color + == tty_status[BEFORE][idx].color) + && (tty_status[NOW][idx].attr + == tty_status[BEFORE][idx].attr)) { + matchprev = TRUE; /* assume success */ + if (tty_status[NOW][idx].dirty) { /* compare values */ - const char *ob, *nb; /* old byte, new byte */ + const char *ob, *nb; /* old byte, new byte */ + struct WinDesc *cw = wins[WIN_STATUS]; c = col - 1; - ob = &wins[WIN_STATUS]->data[row][c]; + ob = &cw->data[row][c]; nb = status_vals[idx]; - while (*nb && c < wins[WIN_STATUS]->cols) { + while (*nb && c < cw->cols) { if (*nb != *ob) break; nb++; ob++; c++; } - if (!*nb && c > col - 1) - matchprev = TRUE; + /* if we're not at the end of new string, no match; + we don't need to worry about whether there might + be leftover old string; that could only happen + if they have different lengths, in which case + 'update_right' will be set and we won't get here */ + if (*nb) + matchprev = FALSE; +#if 0 + if (*nb || (*ob && *ob != ' ' + && (*ob != '/' || idx != BL_XP) + && (*ob != '(' || (idx != BL_HP + && idx != BL_ENE)))) + matchprev = FALSE; +#endif } - } else { - matchprev = FALSE; } } - /* - * With STATUS_HILITES, it is possible that the color - * needs to change even if the text is the same, so - * we flag that here by setting .redraw. - * Then, render_status() will see that flag setting - * and ensure that the tty cell content is updated. - * After the field has been updated, render_status() - * will also clear .redraw and .dirty. - */ 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].dirty && !matchprev)) tty_status[NOW][idx].redraw = TRUE; + col += tty_status[NOW][idx].lth; } - if (idx != -1) { - if (row && bottomsz) - *bottomsz = col + tty_status[NOW][idx].lth; - else if (topsz) - *topsz = col + tty_status[NOW][idx].lth; - } + sz[row] = col; } return valid; } /* * This is what places a field on the tty display. - * If val isn't null, it will be used rather than - * fld (it takes precedence). */ STATIC_OVL void -tty_putstatusfield(fld, val, x, y) -struct tty_status_fields *fld; -const char *val; +tty_putstatusfield(text, x, y) +const char *text; int x, y; { - int i, n, ncols, lth = 0; + int i, n, ncols, nrows, lth = 0; struct WinDesc *cw = 0; - const char *text = (char *)0; - if ((cw = wins[NHW_STATUS]) == (struct WinDesc *) 0) - panic("Invalid WinDesc\n"); + if (WIN_STATUS == WIN_ERR + || (cw = wins[WIN_STATUS]) == (struct WinDesc *) 0) + panic("tty_putstatusfield: Invalid WinDesc\n"); ncols = cw->cols; - if (val) { - text = val; - lth = strlen(text); - } else if (fld) { - text = status_vals[fld->idx]; - lth = fld->lth; - } - if (!text) - return; + nrows = cw->maxrow; + lth = (int) strlen(text); print_vt_code2(AVTC_SELECT_WINDOW, NHW_STATUS); - if (x < ncols && y < 2) { - tty_curs(NHW_STATUS, x, y); + if (x < ncols && y < nrows) { + if (x != cw->curx || y != cw->cury) + tty_curs(NHW_STATUS, x, y); for (i = 0; i < lth; ++i) { n = i + x; if (n < ncols && *text) { (void) putchar(*text); ttyDisplay->curx++; cw->curx++; - cw->data[y][n-1] = *text; + cw->data[y][n - 1] = *text; text++; } } @@ -4096,23 +4145,23 @@ int x, y; } } +/* caller must set cond_shrinklvl (0..2) before calling us */ STATIC_OVL int condition_size() { - long mask = 0L; - int c, x; + long mask; + int c, lth; - x = 0; - for (c = 0; c < SIZE(conditions); ++c) { - mask = conditions[c].mask; - if ((tty_condition_bits & mask) == mask) { - x++; /* for spacer */ - x += (int) strlen(conditions[c].text[cond_shrinklvl]); + lth = 0; + if (tty_condition_bits) { + for (c = 0; c < SIZE(conditions); ++c) { + mask = conditions[c].mask; + if ((tty_condition_bits & mask) == mask) + lth += 1 + (int) strlen(conditions[c].text[cond_shrinklvl]); } } - tty_status[NOW][BL_CONDITION].lth = x; - cond_disp_width[NOW] = x; - return x; + tty_status[NOW][BL_CONDITION].lth = lth; + return lth; } STATIC_OVL void @@ -4120,9 +4169,9 @@ shrink_enc(lvl) int lvl; { /* shrink or restore the encumbrance word */ - if (lvl == 0 || lvl <= 2) { + if (lvl <= 2) { enc_shrinklvl = lvl; - Strcpy(status_vals[BL_CAP], encvals[lvl][enclev]); + Sprintf(status_vals[BL_CAP], " %s", encvals[lvl][enclev]); } tty_status[NOW][BL_CAP].lth = strlen(status_vals[BL_CAP]); } @@ -4154,14 +4203,7 @@ check_windowdata(VOID_ARGS) paniclog("check_windowdata", " null status window."); return FALSE; } else if (!windowdata_init) { - int i, n = wins[WIN_STATUS]->cols; - - for (i = 0; i < wins[WIN_STATUS]->cols; ++i) { - wins[WIN_STATUS]->data[0][i] = ' '; - wins[WIN_STATUS]->data[1][i] = ' '; - } - wins[WIN_STATUS]->data[0][n - 1] = '\0'; /* null terminate */ - wins[WIN_STATUS]->data[1][n - 1] = '\0'; /* null terminate */ + tty_clear_nhwindow(WIN_STATUS); /* also sets cw->data[] to spaces */ windowdata_init = TRUE; } return TRUE; @@ -4263,10 +4305,10 @@ unsigned long *bmarray; STATIC_OVL void render_status(VOID_ARGS) { - long mask = 0L; - int i, c, row, attrmask = 0; + long mask, bits; + int i, x, y, idx, c, row, tlth, num_rows, coloridx = 0, attrmask = 0; + char *text; struct WinDesc *cw = 0; - struct tty_status_fields *nullfield = (struct tty_status_fields *) 0; if (WIN_STATUS == WIN_ERR || (cw = wins[WIN_STATUS]) == (struct WinDesc *) 0) { @@ -4274,22 +4316,19 @@ render_status(VOID_ARGS) return; } - for (row = 0; row < 2; ++row) { + num_rows = (iflags.wc2_statuslines < 3) ? 2 : 3; + for (row = 0; row < num_rows; ++row) { HUPSKIP(); - curs(WIN_STATUS, 1, row); - for (i = 0; fieldorder[row][i] != BL_FLUSH; ++i) { - int idx = fieldorder[row][i]; - + y = row; + tty_curs(WIN_STATUS, 1, y); + for (i = 0; (idx = (*fieldorder)[row][i]) != BL_FLUSH; ++i) { if (!status_activefields[idx]) continue; + x = tty_status[NOW][idx].x; + text = status_vals[idx]; + tlth = (int) tty_status[NOW][idx].lth; - if ((tty_status[NOW][idx].lth || idx == BL_CONDITION) - && (tty_status[NOW][idx].redraw || !do_field_opt)) { - int coloridx = tty_status[NOW][idx].color; - int attridx = tty_status[NOW][idx].attr; - int x = tty_status[NOW][idx].x; - int y = row; - char *text = status_vals[idx]; + if (tty_status[NOW][idx].redraw || !do_field_opt) { boolean hitpointbar = (idx == BL_TITLE && iflags.wc2_hitpointbar); @@ -4299,68 +4338,77 @@ render_status(VOID_ARGS) * | Condition Codes | * +-----------------+ */ + if (!tty_condition_bits) + continue; + if (num_rows == 3) { + int k; + char *dat = &cw->data[y][0]; + + /* line up with hunger (or where it would have + been when currently omitted); if there isn't + enough room for that, right justify; or place + as-is if not even enough room for /that/; we + expect hunger to be on preceding row, in which + case its current data has been moved to [BEFORE] */ + if (tty_status[BEFORE][BL_HUNGER].y < row + && x < tty_status[BEFORE][BL_HUNGER].x + && (tty_status[BEFORE][BL_HUNGER].x + tlth + < cw->cols - 1)) + k = tty_status[BEFORE][BL_HUNGER].x; + else if (x + tlth < cw->cols - 1) + k = cw->cols - tlth; + else + k = x; + while (x < k) { + if (dat[x - 1] != ' ') + tty_putstatusfield(" ", x, y); + ++x; + } + tty_status[NOW][BL_CONDITION].x = x; + tty_curs(WIN_STATUS, x, y); + } + bits = tty_condition_bits; for (c = 0; c < SIZE(conditions); ++c) { mask = conditions[c].mask; - if ((tty_condition_bits & mask) == mask) { + if (bits & mask) { const char *condtext; - tty_putstatusfield(nullfield, " ", x++, y); + tty_putstatusfield(" ", x++, y); if (iflags.hilite_delta) { attrmask = condattr(mask, tty_colormasks); Begin_Attr(attrmask); coloridx = condcolor(mask, tty_colormasks); - if (coloridx != NO_COLOR - && coloridx != CLR_MAX) + if (coloridx != NO_COLOR) term_start_color(coloridx); } - if (x >= cw->cols && !truncation_expected) + condtext = conditions[c].text[cond_shrinklvl]; + if (x >= cw->cols && !truncation_expected) { impossible( "Unexpected condition placement overflow"); - condtext = conditions[c].text[cond_shrinklvl]; - tty_putstatusfield(nullfield, condtext, x, y); + condtext = ""; + } + tty_putstatusfield(condtext, x, y); x += (int) strlen(condtext); if (iflags.hilite_delta) { - if (coloridx != NO_COLOR - && coloridx != CLR_MAX) + if (coloridx != NO_COLOR) term_end_color(); End_Attr(attrmask); } + if (!(bits &= ~mask)) + break; } } - if (x >= cw->cols) { + /* 'x' is 1-based and 'cols' and 'data' are 0-based, + so x==cols means we just stored in data[N-2] and + are now positioned at data[N-1], the terminator; + that's ok as long as we don't write there */ + if (x > cw->cols) { static unsigned once_only = 0; if (!truncation_expected && !once_only++) - paniclog( - "render_status()", " unexpected truncation."); - x = cw->cols - 1; - } - tty_curs(WIN_STATUS, x, y); - cl_end(); - } else if (idx == BL_GOLD) { - char buf[BUFSZ]; - /* - * +-----------+ - * | Gold | - * +-----------+ - */ - if (iflags.hilite_delta) { - if (*text == ' ') { - tty_putstatusfield(nullfield, " ", x++, y); - text++; - } - /* multiple attributes can be in effect concurrently */ - Begin_Attr(attridx); - if (coloridx != NO_COLOR && coloridx != CLR_MAX) - term_start_color(coloridx); - } - /* decode_mixed() due to GOLD glyph */ - tty_putstatusfield(nullfield, - decode_mixed(buf, text), x, y); - if (iflags.hilite_delta) { - if (coloridx != NO_COLOR && coloridx != CLR_MAX) - term_end_color(); - End_Attr(attridx); + paniclog("render_status()", + " unexpected truncation."); + x = cw->cols; } } else if (hitpointbar) { /* @@ -4381,6 +4429,7 @@ render_status(VOID_ARGS) } else Strcpy(bar, text); bar_len = (int) strlen(bar); /* always 30 */ + tlth = bar_len + 2; /* when at full HP, the whole title will be highlighted; when injured or dead, there will be a second portion which is not highlighted */ @@ -4395,12 +4444,12 @@ render_status(VOID_ARGS) savedch = *bar2; *bar2 = '\0'; } - tty_putstatusfield(nullfield, "[", x++, y); + tty_putstatusfield("[", x++, y); if (*bar) { /* always True, unless twoparts+dead (0 HP) */ term_start_attr(ATR_INVERSE); if (iflags.hilite_delta && hpbar_color != NO_COLOR) term_start_color(hpbar_color); - tty_putstatusfield(nullfield, bar, x, y); + tty_putstatusfield(bar, x, y); x += (int) strlen(bar); if (iflags.hilite_delta && hpbar_color != NO_COLOR) term_end_color(); @@ -4408,11 +4457,10 @@ render_status(VOID_ARGS) } if (twoparts) { /* no highlighting for second part */ *bar2 = savedch; - tty_putstatusfield(nullfield, bar2, x, y); + tty_putstatusfield(bar2, x, y); x += (int) strlen(bar2); - /*tty_curs(WIN_STATUS, x, y);*/ } - tty_putstatusfield(nullfield, "]", x++, y); + tty_putstatusfield("]", x++, y); } else { /* * +-----------------------------+ @@ -4421,43 +4469,47 @@ render_status(VOID_ARGS) * +-----------------------------+ */ if (iflags.hilite_delta) { - if (*text == ' ') { - tty_putstatusfield(nullfield, " ", x++, y); + while (*text == ' ') { + tty_putstatusfield(" ", x++, y); text++; } - /* multiple attributes can be in effect concurrently */ - Begin_Attr(attridx); - if (coloridx != NO_COLOR && coloridx != CLR_MAX) + if (*text == '/' && idx == BL_EXP) { + tty_putstatusfield("/", x++, y); + text++; + } + attrmask = tty_status[NOW][idx].attr; + Begin_Attr(attrmask); + coloridx = tty_status[NOW][idx].color; + if (coloridx != NO_COLOR) term_start_color(coloridx); } - tty_putstatusfield(&tty_status[NOW][idx], text, x, y); + tty_putstatusfield(text, x, y); + x += (int) strlen(text); if (iflags.hilite_delta) { - if (coloridx != NO_COLOR && coloridx != CLR_MAX) + if (coloridx != NO_COLOR) term_end_color(); - End_Attr(attridx); + End_Attr(attrmask); } } - if (tty_status[NOW][idx].last_on_row) { - int padright = 0; - - x = tty_status[NOW][idx].x + tty_status[NOW][idx].lth; - finalx[row][NOW] = x - 1; - if (finalx[row][NOW] < finalx[row][BEFORE]) - padright = finalx[row][BEFORE] - finalx[row][NOW]; - while (padright-- > 0) - tty_putstatusfield(nullfield, " ", x++, y); - } + } else { + /* not rendered => same text as before */ + x += tlth; } + finalx[row][NOW] = x - 1; /* reset .redraw, .dirty, .padright now that they're rendered */ tty_status[NOW][idx].dirty = FALSE; tty_status[NOW][idx].redraw = FALSE; - tty_status[NOW][idx].last_on_row = FALSE; - /* * For comparison of current and previous: * - Copy the entire tty_status struct. */ - tty_status[BEFORE][idx] = tty_status[NOW][idx]; + tty_status[BEFORE][idx] = tty_status[NOW][idx]; + } + x = finalx[row][NOW]; + if ((x < finalx[row][BEFORE] || !finalx[row][BEFORE]) + && x + 1 < cw->cols) { + tty_curs(WIN_STATUS, x + 1, y); + cl_end(); } /* * For comparison of current and previous: @@ -4465,12 +4517,6 @@ render_status(VOID_ARGS) */ finalx[row][BEFORE] = finalx[row][NOW]; } - if (cond_disp_width[NOW] < cond_width_at_shrink) { - cond_shrinklvl = 0; /* reset */ - cond_width_at_shrink = condition_size(); - shrink_enc(0); - shrink_dlvl(0); - } return; }