From 382286cb9930f95445d2b1b521dbcbc72a20f5c6 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 25 Mar 2019 16:54:51 -0700 Subject: [PATCH] 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. --- win/curses/cursstat.c | 53 +++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/win/curses/cursstat.c b/win/curses/cursstat.c index 9dfd39fe8..999b1ecda 100644 --- a/win/curses/cursstat.c +++ b/win/curses/cursstat.c @@ -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 -- 2.49.0