TTY_PERM_INVENT fix, part 2 of 2

The problem with tty perminv slots 'A' and 'B' boiled down to
  slot_limit = SIZE(slot_tracker); /*54*/
  ...
  /* blank out unused slots */
  for (slot = 0; slot < slot_limit; ++slot) {
    ...
    row = (slot % rows_per_side) + 1; /* +1: top border */
    side = slot < rows_per_side ? 0 : 1;
    ttyinv_populate_slot(row,side,...);
  }

Unused slots [52] and [53] (available for show_gold mode to display
"$a..zA..Z#", not filled with inventory for normal tty perm_invent
"a..zA..Z") yielded rows 1 and 2, side 1, so clobbered slots 'A' and
'B' with blanks.

This is a subset of the changes I was working with and didn't get as
much testing as the full set.
This commit is contained in:
PatR
2023-10-20 22:52:38 -07:00
parent d96bd6e728
commit a2f80a611a

View File

@@ -1969,8 +1969,11 @@ tty_destroy_nhwindow(winid window)
{
register struct WinDesc *cw = 0;
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) {
if (window == WIN_INVEN) /* Null wins[WIN_INVEN] is tolerated */
return;
panic(winpanicstr, window);
}
if (cw->active)
tty_dismiss_nhwindow(window);
@@ -2974,7 +2977,7 @@ ttyinv_remove_data(boolean destroy)
}
if (destroy) {
cw->maxrow = cw->maxcol = 0;
WIN_INVEN = WIN_ERR;
/*WIN_INVEN = WIN_ERR;*/ /* caller's responsibility */
done_tty_perm_invent_init = FALSE;
}
}
@@ -2985,21 +2988,17 @@ ttyinv_add_menu(winid window UNUSED, struct WinDesc *cw, char ch,
{
char invbuf[BUFSZ];
const char *text;
boolean inuse_only = (ttyinvmode & InvInUse) != 0,
show_gold = (ttyinvmode & InvShowGold) != 0,
/* sparse = (ttyinvmode & InvSparse) != 0, */
boolean show_gold = (ttyinvmode & InvShowGold) != 0,
ignore = FALSE;
int row, side, slot = 0, rows_per_side = (!show_gold ? 26 : 27);
int row, side, slot,
rows_per_side = (!show_gold ? 26 : 27);
if (!gp.program_state.in_moveloop)
return;
slot = selector_to_slot(ch, ttyinvmode, &ignore);
if (!ignore) {
/* inuse_only = ((ttyinvmode & InvInUse) != 0); */
slot_tracker[slot] = TRUE;
text = Empty; /* lint suppression */
/* maxslot = ((int) cw->maxrow - 2) * (!inuse_only ? 2 :
* 1); */
/* maxslot = ((int) cw->maxrow - 2) * (!inuse_only ? 2 : 1); */
/* TODO: check for MENUCOLORS match */
text = str; /* 'text' will switch to invbuf[] below */
@@ -3020,46 +3019,63 @@ ttyinv_add_menu(winid window UNUSED, struct WinDesc *cw, char ch,
text = invbuf;
row = (slot % rows_per_side) + 1; /* +1: top border */
/* side: left side panel or right side panel, not a window column */
side = slot < rows_per_side ? 0 : 1;
if (!(inuse_only && side == 1))
ttyinv_populate_slot(cw, row, side, text, 0);
side = slot / rows_per_side;
ttyinv_populate_slot(cw, row, side, text, 0);
}
return;
}
/* convert a..zA..Z to 0..51 or for 'show_gold' $a..zA..Z# to 0..53 */
static int
selector_to_slot(char ch, const int invflags, boolean *ignore)
{
int slot = 0;
boolean show_gold = (invflags & InvShowGold) != 0,
/* sparse = (invflags & InvSparse) != 0, */
inuse_only = (invflags & InvInUse) != 0;
*ignore = FALSE;
switch (ch) {
case '$':
if (!show_gold)
if (inuse_only) {
/*
* Inuse_only uses slots 0 to N-1 instead of fixed positions.
* Caller--or caller's caller's ... caller--only passes us
* relevant items so no filtering is necessary here; '!show_gold'
* gets ignored here since gold might be quivered or wielded and
* become an in-use item.
* Inuse_only items might include one (or more than one) with
* invlet '#' but it isn't special for Inuse_only.
*/
slot = inuse_only_start++;
} else {
/* normal perminv */
switch (ch) {
case '$':
if (!show_gold)
*ignore = TRUE;
else
slot = 0;
break;
case '#':
/* overflow item won't be gold but there is only room allocated
for it when gold is also eligible to be shown (hero doesn't
have to be carrying any, we just need the extra row it gets) */
if (!show_gold)
*ignore = TRUE;
else
/* fixed location, bottom of right-hand panel; if there is
more than 1 overflow item, we are only able to show 1 */
slot = 0 + 52 + 1; /* 0 for gold, 2 * 26 letters, then '#' */
break;
case '\0':
*ignore = TRUE;
slot = 0;
break;
case '#':
slot = 52 + (show_gold ? 1 : 0);
break;
case 0:
*ignore = TRUE;
break;
default:
if (!inuse_only) {
break;
default:
if (ch >= 'a' && ch <= 'z')
slot = (ch - 'a') + (show_gold ? 1 : 0);
if (ch >= 'A' && ch <= 'Z')
else if (ch >= 'A' && ch <= 'Z')
slot = (ch - 'A') + (show_gold ? 1 : 0) + 26;
} else {
if ((ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z'))
slot = (show_gold ? 1 : 0) + inuse_only_start++;
break;
}
}
} /* normal vs inuse_only */
return slot;
}
@@ -3077,6 +3093,10 @@ ttyinv_render(winid window, struct WinDesc *cw)
slot_limit = SIZE(slot_tracker);
if (inuse_only) {
rows_per_side = cw->maxrow - 2; /* -2 top and bottom borders */
slot_limit = rows_per_side;
} else if (!show_gold) {
slot_limit -= 2; /* slots [52] and [53] would wrap back row 0 and 1,
* attempting to use a non-existent third side */
}
for (slot = 0; slot < slot_limit; ++slot)
if (slot_tracker[slot])
@@ -3085,6 +3105,10 @@ ttyinv_render(winid window, struct WinDesc *cw)
if (slot_tracker[slot])
continue;
if (slot == 0 && !filled_count) {
/* FIXME: this isn't correct; it shows "empty" if hero has gold
and player hasn't set ttyinvmode to display it; it can also
be drawn and briefly seen while other stuff (that player
just dropped or used up) hasn't been erased yet */
Sprintf(invbuf, "%-4s[%s]", "",
!filled_count ? "empty"
: inuse_only ? "no items are in use"
@@ -3095,9 +3119,8 @@ ttyinv_render(winid window, struct WinDesc *cw)
}
row = (slot % rows_per_side) + 1; /* +1: top border */
/* side: left side panel or right side panel, not a window column */
side = slot < rows_per_side ? 0 : 1;
if (!(inuse_only && side == 1))
ttyinv_populate_slot(cw, row, side, text, 0);
side = slot / rows_per_side;
ttyinv_populate_slot(cw, row, side, text, 0);
}
/* has there been a glyph reset since we last got here? */
if (gg.glyph_reset_timestamp > last_glyph_reset_when) {
@@ -3180,13 +3203,14 @@ ttyinv_populate_slot(
struct tty_perminvent_cell *cell;
char c;
int ccnt, col, endcol;
boolean inuse_only = (ttyinvmode & InvInUse) != 0;
/* FIXME: this needs a review. Crashed under InvInUse without */
if ((ttyinvmode & InvInUse) != 0)
col = bordercol[0] + 1;
else
col = bordercol[side] + 1;
if (inuse_only && side == 1) /* there might be more in use than fits */
return;
if (row < 0 || (long) row >= cw->maxrow || side < 0 || side > 1)
panic("ttyinv_populate_slot row=%d, size=%d", row, side);
col = bordercol[side] + 1;
endcol = bordercol[side + 1] - 1;
cell = &cw->cells[row][col];
if (cell->color != color)
@@ -3201,16 +3225,13 @@ ttyinv_populate_slot(
cell->glyph = 0; /* cell->content.gi is gone */
}
if ((c = *text) != '\0') {
if (cell->content.ttychar != c)
cell->refresh = 1;
cell->content.ttychar = c;
if ((c = *text) != '\0')
++text;
} else {
if (cell->content.ttychar != ' ')
cell->refresh = 1;
cell->content.ttychar = ' ';
}
else
c = ' ';
if (cell->content.ttychar != c)
cell->refresh = 1;
cell->content.ttychar = c;
cell->text = 1; /* cell->content.ttychar is current */
}
}