fix #K4058 - tty: perm_invent fixes

I think this fixes all problems with the boundary boz drawn around
perm_invent.  Also, if you enabled perm_invent in inuse_only mode
while there are already more items in use than would fix in the
available number of lines, it wasn't switching to two columns until
the next update_inventory().  And the new color handling wasn't
incorporate into tty_refresh_inventory() so after a corner window
clobbered some of perm_invent, it got redrawn but without color,
again until the next update_inventory().

With any luck this fixes more bugs than it introduces....
This commit is contained in:
PatR
2023-12-07 03:22:44 -08:00
parent 7c20bf4afa
commit 634f492827

View File

@@ -180,7 +180,7 @@ static volatile int erasing_tty_screen; /* volatile: SIGWINCH */
static char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ static char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
#endif #endif
static char winpanicstr[] = "Bad window Id %d (%s)"; static const char winpanicstr[] = "Bad window Id %d (%s)";
#define ttywindowpanic() panic(winpanicstr, window, __func__) #define ttywindowpanic() panic(winpanicstr, window, __func__)
char defmorestr[] = "--More--"; char defmorestr[] = "--More--";
@@ -253,7 +253,9 @@ void g_pututf8(uint8 *utf8str);
#endif #endif
#ifdef TTY_PERM_INVENT #ifdef TTY_PERM_INVENT
static struct tty_perminvent_cell zerottycell = { 0, 0, 0, { 0 }, 0 }; static struct tty_perminvent_cell emptyttycell = {
0, 0, 0, { 0 }, NO_COLOR + 1
};
static glyph_info zerogi = { 0 }; static glyph_info zerogi = { 0 };
static struct to_core zero_tocore = { 0 }; static struct to_core zero_tocore = { 0 };
enum { border_left, border_middle, border_right, border_elements }; enum { border_left, border_middle, border_right, border_elements };
@@ -959,7 +961,10 @@ tty_create_nhwindow(int type)
RESTORE_WARNING_UNREACHABLE_CODE RESTORE_WARNING_UNREACHABLE_CODE
static void static void
erase_menu_or_text(winid window, struct WinDesc *cw, boolean clear) erase_menu_or_text(
winid window,
struct WinDesc *cw,
boolean clear)
{ {
if (cw->offx == 0) { if (cw->offx == 0) {
if (cw->offy) { if (cw->offy) {
@@ -1023,8 +1028,6 @@ free_window_info(struct WinDesc *cw, boolean free_data)
} }
} }
DISABLE_WARNING_FORMAT_NONLITERAL
void void
tty_clear_nhwindow(winid window) tty_clear_nhwindow(winid window)
{ {
@@ -1100,8 +1103,6 @@ tty_clear_nhwindow(winid window)
/* cw->blanked = TRUE; -- this isn't used */ /* cw->blanked = TRUE; -- this isn't used */
} }
RESTORE_WARNING_FORMAT_NONLITERAL
/* toggle a specific entry */ /* toggle a specific entry */
static boolean static boolean
toggle_menu_curr( toggle_menu_curr(
@@ -1815,8 +1816,6 @@ process_text_window(winid window, struct WinDesc *cw)
} }
} }
DISABLE_WARNING_FORMAT_NONLITERAL /* RESTORE after tty_select_menu */
/*ARGSUSED*/ /*ARGSUSED*/
void void
tty_display_nhwindow( tty_display_nhwindow(
@@ -2798,10 +2797,11 @@ tty_message_menu(char let, int how, const char *mesg)
return ((how == PICK_ONE && morc == let) || morc == '\033') ? morc : '\0'; return ((how == PICK_ONE && morc == let) || morc == '\033') ? morc : '\0';
} }
RESTORE_WARNING_FORMAT_NONLITERAL
win_request_info * win_request_info *
tty_ctrl_nhwindow(winid window UNUSED, int request, win_request_info *wri) tty_ctrl_nhwindow(
winid window UNUSED,
int request,
win_request_info *wri)
{ {
#if defined(TTY_PERM_INVENT) #if defined(TTY_PERM_INVENT)
boolean tty_ok /*, show_gold */, inuse_only; boolean tty_ok /*, show_gold */, inuse_only;
@@ -2859,7 +2859,7 @@ tty_ctrl_nhwindow(winid window UNUSED, int request, win_request_info *wri)
static int static int
ttyinv_create_window(int newid, struct WinDesc *newwin) ttyinv_create_window(int newid, struct WinDesc *newwin)
{ {
int i, r, c; int r, c;
long minrow; /* long to match maxrow declaration */ long minrow; /* long to match maxrow declaration */
unsigned n; unsigned n;
@@ -2897,14 +2897,17 @@ ttyinv_create_window(int newid, struct WinDesc *newwin)
if (!assesstty(ttyinvmode, &newwin->offx, &newwin->offy, &newwin->rows, if (!assesstty(ttyinvmode, &newwin->offx, &newwin->offy, &newwin->rows,
&newwin->cols, &newwin->maxcol, &minrow, &newwin->cols, &newwin->maxcol, &minrow,
&newwin->maxrow)) { &newwin->maxrow)) {
tty_destroy_nhwindow(newid); /* sets WIN_INVEN to WIN_ERR */ tty_destroy_nhwindow(newid);
WIN_INVEN = WIN_ERR;
pline("%s.", "tty perm_invent could not be enabled"); pline("%s.", "tty perm_invent could not be enabled");
pline("tty perm_invent needs a terminal that is at least %dx%d, " pline("tty perm_invent needs a terminal that is at least %dx%d, "
"yours is %dx%d.", "yours is %dx%d.",
(int) (minrow + 1 + ROWNO + StatusRows()), tty_perminv_mincol, (int) (minrow + 1 + ROWNO + StatusRows()), tty_perminv_mincol,
ttyDisplay->rows, ttyDisplay->cols); ttyDisplay->rows, ttyDisplay->cols);
tty_wait_synch(); tty_wait_synch();
#ifndef RESIZABLE
set_option_mod_status("perm_invent", set_gameview); set_option_mod_status("perm_invent", set_gameview);
#endif
iflags.perm_invent = FALSE; iflags.perm_invent = FALSE;
return WIN_ERR; return WIN_ERR;
} }
@@ -2922,30 +2925,20 @@ ttyinv_create_window(int newid, struct WinDesc *newwin)
there are more items than the number of full lines */ there are more items than the number of full lines */
if ((ttyinvmode & InvInUse) != 0) if ((ttyinvmode & InvInUse) != 0)
bordercol[border_middle] = bordercol[border_right]; bordercol[border_middle] = bordercol[border_right];
ttyinv_slots_used = 0;
n = (unsigned) (newwin->maxrow * sizeof (struct tty_perminvent_cell *)); n = (unsigned) (newwin->maxrow * sizeof (struct tty_perminvent_cell *));
newwin->cells = (struct tty_perminvent_cell **) alloc(n); newwin->cells = (struct tty_perminvent_cell **) alloc(n);
n = (unsigned) (newwin->maxcol * sizeof (struct tty_perminvent_cell)); n = (unsigned) (newwin->maxcol * sizeof (struct tty_perminvent_cell));
for (i = 0; i < newwin->maxrow; i++) for (r = 0; r < newwin->maxrow; r++) {
newwin->cells[i] = (struct tty_perminvent_cell *) alloc(n); newwin->cells[r] = (struct tty_perminvent_cell *) alloc(n);
for (c = 0; c < newwin->maxcol; c++)
n = (unsigned) sizeof (glyph_info); newwin->cells[r][c] = emptyttycell;
for (r = 0; r < newwin->maxrow; r++) }
for (c = 0; c < newwin->maxcol; c++) {
newwin->cells[r][c] = zerottycell;
if (r == 0 || r == newwin->maxrow - 1
|| c == bordercol[border_left]
|| c == bordercol[border_middle]
|| c == bordercol[border_right]) {
newwin->cells[r][c].content.gi = (glyph_info *) alloc(n);
*newwin->cells[r][c].content.gi = zerogi;
newwin->cells[r][c].glyph = 1;
}
}
newwin->active = 1; newwin->active = 1;
ttyinv_slots_used = 0;
tty_invent_box_glyph_init(newwin); tty_invent_box_glyph_init(newwin);
return newid; return newid;
} }
@@ -2972,7 +2965,7 @@ ttyinv_remove_data(boolean destroy)
contains a glyph_info structure or just a char */ contains a glyph_info structure or just a char */
if (invcell->glyph) if (invcell->glyph)
free((genericptr_t) invcell->content.gi); free((genericptr_t) invcell->content.gi);
*invcell = zerottycell; /* sets glyph flag to 0 */ *invcell = emptyttycell; /* sets glyph flag to 0 */
if (!destroy) { /* erasing */ if (!destroy) { /* erasing */
invcell->content.ttychar = ' '; invcell->content.ttychar = ' ';
invcell->text = 1; invcell->text = 1;
@@ -2995,6 +2988,7 @@ ttyinv_remove_data(boolean destroy)
/*WIN_INVEN = WIN_ERR;*/ /* caller's responsibility */ /*WIN_INVEN = WIN_ERR;*/ /* caller's responsibility */
done_tty_perm_invent_init = FALSE; done_tty_perm_invent_init = FALSE;
} }
ttyinv_slots_used = 0; /* reset: inuse_only isn't using any slots */
} }
static void static void
@@ -3028,9 +3022,10 @@ ttyinv_add_menu(
slots 0 thru rows_per_side-1, so zero-based slot==rows_per_side slots 0 thru rows_per_side-1, so zero-based slot==rows_per_side
is the entry that will be shown on first row of the second side is the entry that will be shown on first row of the second side
(and one-base ttyinv_slots_used==rows_per_side means that on the (and one-base ttyinv_slots_used==rows_per_side means that on the
previous inventory_update(), full lines filled all the rows) */ previous inventory_update(), full lines filled all the rows;
ttyinv_slots_used==0 means that we've just enabled perm_invent) */
if (inuse_only && slot == rows_per_side if (inuse_only && slot == rows_per_side
&& ttyinv_slots_used == rows_per_side) && ttyinv_slots_used % rows_per_side == 0)
ttyinv_inuse_twosides(cw, rows_per_side); ttyinv_inuse_twosides(cw, rows_per_side);
text = str; /* 'text' will switch to invbuf[] below */ text = str; /* 'text' will switch to invbuf[] below */
@@ -3056,7 +3051,7 @@ ttyinv_add_menu(
*/ */
Snprintf(invbuf, sizeof invbuf, "%c - %s", ch, text); Snprintf(invbuf, sizeof invbuf, "%c - %s", ch, text);
text = invbuf; text = invbuf;
startcolor_at = sizeof ("a - ") - 1; startcolor_at = (int) (sizeof "a - " - sizeof ""); /* 4 */
row = (slot % rows_per_side) + 1; /* +1: top border */ row = (slot % rows_per_side) + 1; /* +1: top border */
/* side: left side panel or right side panel, not a window column */ /* side: left side panel or right side panel, not a window column */
side = slot / rows_per_side; side = slot / rows_per_side;
@@ -3209,7 +3204,7 @@ ttyinv_end_menu(int window, struct WinDesc *cw)
} }
} }
/* display persistent inventory */ /* display persistent inventory from data collected by add_menu() */
static void static void
ttyinv_render(winid window, struct WinDesc *cw) ttyinv_render(winid window, struct WinDesc *cw)
{ {
@@ -3228,7 +3223,7 @@ ttyinv_render(winid window, struct WinDesc *cw)
slot_limit = SIZE(slot_tracker); slot_limit = SIZE(slot_tracker);
if (inuse_only) { if (inuse_only) {
slot_limit = rows_per_side; /* assume one side */ slot_limit = rows_per_side; /* assume one side */
if (ttyinv_slots_used >= rows_per_side) if (ttyinv_slots_used == 0 || ttyinv_slots_used >= rows_per_side)
slot_limit *= 2; /* second side is populated */ slot_limit *= 2; /* second side is populated */
} else if (!show_gold) { } else if (!show_gold) {
slot_limit -= 2; /* there are two extra slots for gold and overflow; slot_limit -= 2; /* there are two extra slots for gold and overflow;
@@ -3287,12 +3282,13 @@ ttyinv_render(winid window, struct WinDesc *cw)
for (col = 0; col < cw->maxcol; ++col) { for (col = 0; col < cw->maxcol; ++col) {
cell = &cw->cells[row][col]; cell = &cw->cells[row][col];
if (cell->refresh || force_redraw) { if (cell->refresh || force_redraw) {
if (cell->color if (cell->color && (current_row_color != cell->color - 1)) {
&& (current_row_color != cell->color - 1)) {
current_row_color = cell->color - 1; current_row_color = cell->color - 1;
#if 0
if (current_row_color == NO_COLOR) if (current_row_color == NO_COLOR)
term_end_color(); term_end_color();
else else
#endif
term_start_color(current_row_color); term_start_color(current_row_color);
} }
if (cell->glyph) { if (cell->glyph) {
@@ -3350,7 +3346,7 @@ ttyinv_populate_slot(
each other in a union, so clear gi before assigning ttychar */ each other in a union, so clear gi before assigning ttychar */
if (cell->glyph) { if (cell->glyph) {
free((genericptr_t) cell->content.gi); free((genericptr_t) cell->content.gi);
*cell = zerottycell; /* clears cell->glyph and cell->content */ *cell = emptyttycell; /* clears cell->glyph and cell->content */
} }
if ((c = *text) != '\0') if ((c = *text) != '\0')
@@ -3374,8 +3370,6 @@ ttyinv_populate_slot(
} }
} }
DISABLE_WARNING_FORMAT_NONLITERAL
void void
tty_refresh_inventory(int start, int stop, int y) tty_refresh_inventory(int start, int stop, int y)
{ {
@@ -3383,8 +3377,10 @@ tty_refresh_inventory(int start, int stop, int y)
struct WinDesc *cw = 0; struct WinDesc *cw = 0;
winid window = WIN_INVEN; winid window = WIN_INVEN;
struct tty_perminvent_cell *cell; struct tty_perminvent_cell *cell;
boolean printing_glyphs;
if (window == WIN_ERR || !iflags.perm_invent || y < 0) if (window == WIN_ERR || !iflags.perm_invent
|| gp.perm_invent_toggling_direction == toggling_off)
return; return;
if ((cw = wins[window]) == (struct WinDesc *) 0) if ((cw = wins[window]) == (struct WinDesc *) 0)
@@ -3393,17 +3389,21 @@ tty_refresh_inventory(int start, int stop, int y)
if (col_limit > cw->maxcol) if (col_limit > cw->maxcol)
col_limit = cw->maxcol; col_limit = cw->maxcol;
if (row >= cw->maxrow)
return; /* out of our range. Huge menus can do this */
/* we've been asked to redisplay a portion of the screen, one row */ /* we've been asked to redisplay a portion of the screen, one row */
printing_glyphs = FALSE;
for (col = start - 1; col < col_limit; ++col) { for (col = start - 1; col < col_limit; ++col) {
cell = &cw->cells[row][col]; cell = &cw->cells[row][col];
if (cell->color != ttyDisplay->color + 1) {
term_start_color(cell->color - 1);
ttyDisplay->color = cell->color - 1;
}
if (cell->glyph) { if (cell->glyph) {
tty_print_glyph(window, col + 1, row, cell->content.gi, tty_print_glyph(window, col + 1, row, cell->content.gi,
&nul_glyphinfo); &nul_glyphinfo);
end_glyphout(); printing_glyphs = TRUE;
} else { } else {
if (printing_glyphs)
end_glyphout();
if (col != cw->curx || row != cw->cury) if (col != cw->curx || row != cw->cury)
tty_curs(window, col + 1, row); tty_curs(window, col + 1, row);
(void) putchar(cell->content.ttychar); (void) putchar(cell->content.ttychar);
@@ -3412,16 +3412,26 @@ tty_refresh_inventory(int start, int stop, int y)
} }
cell->refresh = 0; cell->refresh = 0;
} }
if (printing_glyphs)
end_glyphout();
if (ttyDisplay->color != NO_COLOR) {
term_end_color();
ttyDisplay->color = NO_COLOR;
}
} }
RESTORE_WARNING_FORMAT_NONLITERAL
static void static void
tty_invent_box_glyph_init(struct WinDesc *cw) tty_invent_box_glyph_init(struct WinDesc *cw)
{ {
int row, col, glyph, bordercolor = NO_COLOR; int row, col, glyph, bordercolor = NO_COLOR;
uchar sym; uchar sym;
struct tty_perminvent_cell *cell; struct tty_perminvent_cell *cell;
boolean inuse_only = (ttyinvmode & InvInUse) != 0,
show_gold = (ttyinvmode & InvShowGold) != 0 && !inuse_only;
int rows_per_side = (inuse_only ? (cw->maxrow - 2)
: !show_gold ? 26
: 27),
bottomrow = rows_per_side + 1;
if (cw == 0 || !cw->active) if (cw == 0 || !cw->active)
return; return;
@@ -3434,50 +3444,35 @@ tty_invent_box_glyph_init(struct WinDesc *cw)
[border_middle] because they could be the same column (for [border_middle] because they could be the same column (for
InvInUse) and if so we want corner rather than tee there */ InvInUse) and if so we want corner rather than tee there */
if (row == 0) { if (row == 0) {
if (col == bordercol[border_left]) sym = (col == bordercol[border_left]) ? S_tlcorn
sym = S_tlcorn; : (col == bordercol[border_right]) ? S_trcorn
else if (col == bordercol[border_right]) : (col == bordercol[border_middle]) ? S_tdwall
sym = S_trcorn; : S_hwall;
else if (col == bordercol[border_middle]) } else if (row < bottomrow) {
sym = S_tdwall;
else /*if ((col > bordercol[border_left]
&& col < bordercol[border_middle])
|| (col > bordercol[border_middle]
&& col < bordercol[border_right]))*/
sym = S_hwall;
} else if (row == (cw->maxrow - 1)) {
if (col == bordercol[border_left])
sym = S_blcorn;
else if (col == bordercol[border_right])
sym = S_brcorn;
else if (col == bordercol[border_middle])
sym = S_tuwall;
else /*if ((col > bordercol[border_left]
&& col < bordercol[border_middle])
|| (col > bordercol[border_middle]
&& col < bordercol[border_right]))*/
sym = S_hwall;
} else {
if (col == bordercol[border_left] if (col == bordercol[border_left]
|| col == bordercol[border_middle] || col == bordercol[border_middle]
|| col == bordercol[border_right]) || col == bordercol[border_right])
sym = S_vwall; sym = S_vwall;
/* else sym keeps placeholder value */
} else if (row == bottomrow) {
sym = (col == bordercol[border_left]) ? S_blcorn
: (col == bordercol[border_right]) ? S_brcorn
: (col == bordercol[border_middle]) ? S_tuwall
: S_hwall;
} }
if (sym == S_crwall) { /* not a boundary (but might have been) */ if (sym == S_crwall) { /* not a boundary (but might have been) */
if (cell->glyph) { if (cell->glyph) {
/* presumably is no longer wanted middle vertical line */ /* presumably is no longer wanted middle vertical line */
free((genericptr_t) cell->content.gi); free((genericptr_t) cell->content.gi);
*cell = zerottycell; /* clears cell->glyph */ *cell = emptyttycell; /* clears cell->glyph */
cell->content.ttychar = ' '; cell->content.ttychar = ' ';
cell->text = 1; cell->text = 1;
cell->refresh = 1; cell->refresh = 1;
} }
continue; continue;
} }
/* a boundary, but might not have been if this is the middle /* a boundary; if it doesn't hold a glyph yet, allocate one */
and we were showing full lines and are now going to show two
sides; allocate glyph_info for middle vertical line */
if (!cell->glyph) { if (!cell->glyph) {
cell->content.gi = (glyph_info *) alloc(sizeof (glyph_info)); cell->content.gi = (glyph_info *) alloc(sizeof (glyph_info));
*(cell->content.gi) = zerogi; *(cell->content.gi) = zerogi;
@@ -3489,7 +3484,7 @@ tty_invent_box_glyph_init(struct WinDesc *cw)
map_glyphinfo(0, 0, glyph, 0, cell->content.gi); map_glyphinfo(0, 0, glyph, 0, cell->content.gi);
cell->glyph = 1; /* (redundant) */ cell->glyph = 1; /* (redundant) */
cell->text = 0; cell->text = 0;
/* originaly this conditionally set refresh depending upon /* originally this conditionally set refresh depending upon
whether the glyph was already shown, but that optimization whether the glyph was already shown, but that optimization
is for something that rarely happens (boundary lines aren't is for something that rarely happens (boundary lines aren't
redrawn very often, and most of the time when they are it's redrawn very often, and most of the time when they are it's
@@ -3512,15 +3507,14 @@ assesstty(
{ {
boolean inuse_only = (invmode & InvInUse) != 0, boolean inuse_only = (invmode & InvInUse) != 0,
show_gold = (invmode & InvShowGold) != 0 && !inuse_only; show_gold = (invmode & InvShowGold) != 0 && !inuse_only;
int perminv_minrow = tty_perminv_minrow + (show_gold ? 1 : 0);
*offx = 0; *offx = 0;
/* topline + map rows + status lines */ /* topline + map rows + status lines */
*offy = 1 + ROWNO + StatusRows(); /* 1 + 21 + (2 or 3) */ *offy = 1 + ROWNO + StatusRows(); /* 1 + 21 + (2 or 3) */
*rows = (ttyDisplay->rows - *offy); *rows = (ttyDisplay->rows - *offy);
*cols = ttyDisplay->cols; *cols = ttyDisplay->cols;
*minrow = tty_perminv_minrow; *minrow = perminv_minrow;
if (show_gold)
*minrow += 1;
#define SMALL_INUSE_WINDOW #define SMALL_INUSE_WINDOW
#ifdef SMALL_INUSE_WINDOW #ifdef SMALL_INUSE_WINDOW
#undef SMALL_INUSE_WINDOW #undef SMALL_INUSE_WINDOW
@@ -3535,7 +3529,7 @@ assesstty(
if (inuse_only) if (inuse_only)
*minrow = 1 + 15 + 1; /* top border + 15 lines + bottom border */ *minrow = 1 + 15 + 1; /* top border + 15 lines + bottom border */
#endif #endif
*maxrow = *rows; *maxrow = min(*rows, perminv_minrow);
*maxcol = *cols; *maxcol = *cols;
return !(*rows < *minrow || *cols < tty_perminv_mincol); return !(*rows < *minrow || *cols < tty_perminv_mincol);
} }
@@ -3599,7 +3593,7 @@ docorner(
#ifdef TTY_PERM_INVENT #ifdef TTY_PERM_INVENT
struct WinDesc *icw = 0; struct WinDesc *icw = 0;
if (WIN_INVEN != WIN_ERR) if (WIN_INVEN != WIN_ERR && iflags.perm_invent)
icw = wins[WIN_INVEN]; icw = wins[WIN_INVEN];
#endif #endif
@@ -3628,8 +3622,9 @@ docorner(
if (!ystart_between_menu_pages) if (!ystart_between_menu_pages)
cl_end(); /* clear to end of line */ cl_end(); /* clear to end of line */
#ifdef TTY_PERM_INVENT #ifdef TTY_PERM_INVENT
/* the whole thing is beyond the board */ /* the whole thing is beyond the board but not necessarily all the
if (icw) way to the bottom of the screen */
if (icw && y >= (int) icw->offy && y < icw->offy + icw->maxrow)
tty_refresh_inventory(xmin - (int) icw->offx, icw->maxcol, tty_refresh_inventory(xmin - (int) icw->offx, icw->maxcol,
y - (int) icw->offy); y - (int) icw->offy);
#endif #endif