curses status display

I noticed a couple of things wrong--that I was fairly sure that I
had working correctly before--and after fixing the second one, the
first has mysteriously disappeared.

First problem, which may or may not still be a problem:  extra spaces
were being removed from the second line of 2-line status even though
there were still 4 or 5 available spaces to the right of the status
conditions.  It was behaving as if it thought the line was narrower
than actual size, or conversely, that the sum of the widths of the
fields plus the extra spaces was bigger than it actually was.

Second problem, fixed here.  The code to put '+' in the far right
column of the last status line when there is at least one condition
all the way off the display wasn't working right when windowborders
were displayed.  That's down to curses wrapping to the next line but
user can't see it due to the window border overwriting.  Single char
overflow stayed on same line, but two or more wrapped and then the
'x' coordinate didn't match tests for 'too wide'.  Perform explicit
truncation instead of leaving that up to curses.  Also truncate
encumbrance when warranted since it's feasible for it to overflow.
Anyone using a display narrower than 80 columns might still run
into odd status behavior because other fields than conditions and
encumbrance could go past the end of line.  But they shouldn't be
wasting screen real estate with windowborders, and without borders,
curses will keep the cursor in the bottom right corner when the
program tries to go past, which should keep things reasonably sane.
This commit is contained in:
PatR
2019-03-25 16:54:51 -07:00
parent 2960042a9f
commit 382286cb99

View File

@@ -301,14 +301,14 @@ unsigned long *colormasks;
const enum statusfields (*fieldorder)[3][15];
xchar spacing[MAXBLSTATS], valline[MAXBLSTATS];
enum statusfields fld, prev_fld;
char *text, *p, cbuf[BUFSZ];
char *text, *p, cbuf[BUFSZ], ebuf[STATVAL_WIDTH];
#ifdef SCORE_ON_BOTL
char *colon;
char sbuf[STATVAL_WIDTH];
#endif
int i, j, number_of_lines,
cap_and_hunger, exp_points, sho_score,
height, width, w, xtra, clen, x, y, t,
height, width, w, xtra, clen, x, y, t, ex, ey,
condstart = 0, conddummy = 0;
int coloridx = NO_COLOR, attrmask = 0;
boolean asis = FALSE;
@@ -367,7 +367,7 @@ unsigned long *colormasks;
startover:
/* first pass for line #j -- figure out spacing */
(void) memset((genericptr_t) spacing, 0, sizeof spacing);
w = xtra = 0;
w = xtra = 0; /* w: width so far; xtra: number of extra spaces */
prev_fld = BL_FLUSH;
for (i = 0; (fld = (*fieldorder)[j][i]) != BL_FLUSH; ++i) {
text = status_vals[fld];
@@ -403,7 +403,7 @@ unsigned long *colormasks;
/*FALLTHRU*/
case BL_ALIGN:
case BL_LEVELDESC:
spacing[fld] = (i > 0 ? 1 : 0);
spacing[fld] = (i > 0 ? 1 : 0); /* extra space unless first */
break;
case BL_HUNGER:
spacing[fld] = (cap_and_hunger & 1);
@@ -525,6 +525,19 @@ unsigned long *colormasks;
/* always enabled but might be empty */
if (!(cap_and_hunger & 2))
continue;
/* check whether encumbrance is going to go past right edge
and wrap; if so, truncate it; (won't wrap on last line
of borderless window, but will when there's a border);
could only do that after all extra spaces are gone */
if (!xtra) {
getyx(win, ey, ex);
t = (int) strlen(text);
if (ex + t > width - (border ? 0 : 1)) {
text = strcpy(ebuf, text);
t = (width - (border ? 0 : 1)) - (ex - 1);
ebuf[max(t, 2)] = '\0'; /* might still wrap... */
}
}
break;
case BL_SCORE:
#ifdef SCORE_ON_BOTL
@@ -545,7 +558,7 @@ unsigned long *colormasks;
if (fld == BL_TITLE && iflags.wc2_hitpointbar) {
/* hitpointbar using hp percent calculation; title width
is padded to 30 if shorter, truncated at 30 if longer;
otherall width is 32 because of the enclosing brackets */
overall width is 32 because of the enclosing brackets */
curs_HPbar(text, 0);
} else if (fld != BL_CONDITION) {
@@ -584,6 +597,12 @@ unsigned long *colormasks;
/* status conditions */
if (curses_condition_bits) {
getyx(win, y, x);
/* encumbrance is truncated if too wide, but other fields
aren't; if window is narrower than normal, last field
written might have wrapped to the next line */
if (y > j + (border ? 1 : 0))
x = width - (border ? -1 : 0), /* (width-=2 above) */
y = j + (border ? 1 : 0);
/* cbuf[] was populated above; clen is its length */
if (number_of_lines == 3) {
/*
@@ -610,7 +629,7 @@ unsigned long *colormasks;
condition string as-is if it will overflow; we
want curs_stat_conds() to write '+' in last column
if any conditions are all the way off the edge */
if (x + clen <= width - (border ? 1 : 0))
if (x + clen > width - (border ? 1 : 0))
asis = FALSE;
if (asis)
@@ -967,8 +986,8 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
for (i = 0; i < BL_MASK_BITS; ++i) {
bitmsk = valid_conditions[i].bitmask;
if (curses_condition_bits & bitmsk) {
Strcat(strcat(condbuf, " "),
upstart(strcpy(condnam, valid_conditions[i].id)));
Strcpy(condnam, valid_conditions[i].id);
Strcat(strcat(condbuf, " "), upstart(condnam));
if (nohilite && *nohilite
&& (condcolor(bitmsk, colormasks) != NO_COLOR
|| condattr(bitmsk, colormasks) != 0))
@@ -977,7 +996,8 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
}
} else if (curses_condition_bits) {
unsigned long cond_bits;
int height = 0, width, cx, cy, cy0, attrmask = 0, color = NO_COLOR;
int height = 0, width, cx, cy, cy0, cndlen,
attrmask = 0, color = NO_COLOR;
boolean border, do_vert = (vert_cond != 0);
WINDOW *win = curses_get_nhwin(STATUS_WIN);
@@ -990,10 +1010,19 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
for (i = 0; i < BL_MASK_BITS; ++i) {
bitmsk = valid_conditions[i].bitmask;
if (cond_bits & bitmsk) {
Strcpy(condnam, valid_conditions[i].id);
cndlen = 1 + (int) strlen(condnam); /* count leading space */
if (!do_vert) {
getyx(win, cy, cx);
if (cx >= width - (border ? 2 : 1) || (border && cy > cy0))
break; /* skip rest if not enough room for any more */
if (cy > cy0) /* wrap to next line shouldn't happen */
cx = width, cy = cy0;
if (cx + cndlen > width - (border ? 2 : 1)) {
/* not enough room for current condition */
if (cx + 1 > width - (border ? 2 : 1))
break; /* no room at all; skip it and the rest */
/* room for part; truncate it to avoid wrapping */
condnam[width - (border ? 2 : 1) - cx] = '\0';
}
}
cond_bits &= ~bitmsk; /* nonzero if another cond after this */
/* output unhighlighted leading space unless at #1 of 3 */
@@ -1011,7 +1040,7 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
}
/* output the condition name */
waddstr(win, upstart(strcpy(condnam, valid_conditions[i].id)));
waddstr(win, upstart(condnam));
if (iflags.hilite_delta) {
#ifdef TEXTCOLOR