]> granicus.if.org Git - nethack/commitdiff
experimental config option TTY_PERM_INVENT
authornhmall <nhmall@nethack.org>
Mon, 20 Jun 2022 14:40:55 +0000 (10:40 -0400)
committernhmall <nhmall@nethack.org>
Mon, 20 Jun 2022 14:40:55 +0000 (10:40 -0400)
Add a rudimentary experimental always-up inventory display
capability to tty when the perm_invent option is in effect.
It requires an additional 28 rows available on the terminal
underneath the bottom status line.

It hasn't been optimized for performance as of yet.

include/config.h
include/decl.h
include/wintty.h
src/allmain.c
src/decl.c
src/display.c
src/options.c
sys/windows/consoletty.c
sys/windows/stubs.c
win/tty/wintty.c

index 9c59cb9eb99580b4571e6b1891e78c6b4379bc1d..9ed4e3273fcb8b70c8f08a05143f6f7db8e37bef 100644 (file)
@@ -560,6 +560,10 @@ typedef unsigned char uchar;
 /* #define TTY_TILES_ESCCODES */
 /* #define TTY_SOUND_ESCCODES */
 
+/* An experimental minimalist inventory list capability under tty if you have
+ * at least 28 additional rows beneath the status window on your terminal  */
+/* #define TTY_PERM_INVENT */
+
 /* NetHack will execute an external program whenever a new message-window
  * message is shown.  The program to execute is given in environment variable
  * NETHACK_MSGHANDLER.  It will get the message as the only parameter.
index b9c42bbb53d15592e8c57f3b2bb56ae55cc2e187..67598d852fe431ed8528addcd72492258a61dae4 100644 (file)
@@ -98,6 +98,7 @@ struct sinfo {
     int restoring;
     int in_moveloop;
     int in_impossible;
+    int in_docrt;               /* in docrt() */
     int in_self_recover;
     int in_parseoptions;        /* in parseoptions */
     int config_error_ready;     /* config_error_add is ready, available */
@@ -971,6 +972,9 @@ struct instance_globals {
        persistent one doesn't get shrunk during filtering for item selection
        then regrown to full inventory, possibly being resized in the process */
     winid cached_pickinv_win;
+#ifdef TTY_PERM_INVENT
+    winid tty_invent_win;
+#endif
     /* query objlist callback: return TRUE if obj type matches "this_type" */
     int this_type;
     const char *this_title; /* title for inventory list of specific type */
index f28c819be587188538f19323e5fbaf157d7384a0..1c7bf527ecc75e1d6e899f2cefd938afc56356d2 100644 (file)
 #ifndef WINDOW_STRUCTS
 #define WINDOW_STRUCTS
 
+#ifdef TTY_PERM_INVENT
+enum { tty_pi_minrow = 28, tty_pi_mincol = 79 };
+union ttycellcontent {
+    char ttychar;
+    glyph_info *gi;
+};
+struct tty_perminvent_cell {
+    Bitfield(refresh, 1);
+    Bitfield(text, 1);
+    Bitfield(glyph, 1);
+    Bitfield(colorbits, 5);
+    union ttycellcontent content;
+    int32_t color;
+};
+extern struct tty_perminvent_cell zerottycell;
+#endif
+
 /* menu structure */
 typedef struct tty_mi {
     struct tty_mi *next;
@@ -45,6 +62,9 @@ struct WinDesc {
     long nitems;           /* total number of items (MENU) */
     short how;             /* menu mode - pick 1 or N (MENU) */
     char menu_ch;          /* menu char (MENU) */
+#ifdef TTY_PERM_INVENT
+    struct tty_perminvent_cell **cells;
+#endif
 };
 
 /* window flags */
@@ -103,7 +123,11 @@ struct tty_status_fields {
 #ifdef NHW_BASE
 #undef NHW_BASE
 #endif
-#define NHW_BASE 6
+#define NHW_BASE (NHW_TEXT + 1)
+
+#ifdef TTY_PERM_INVENT
+#define NHW_TTYINVENT (NHW_BASE + 1)
+#endif
 
 extern struct window_procs tty_procs;
 
@@ -261,6 +285,10 @@ E void genl_outrip(winid, int, time_t);
 E char *tty_getmsghistory(boolean);
 E void tty_putmsghistory(const char *, boolean);
 
+#ifdef TTY_PERM_INVENT
+E void tty_refresh_inventory(int start, int stop, int y);
+#endif
+
 #ifdef NO_TERMS
 #ifdef MAC
 #ifdef putchar
index 70346a75d9496a2ae7684362cea51fa8ac6b6239..a39f5d21638bdda4d73d8850561121922a1433e8 100644 (file)
 #include <signal.h>
 #endif
 
+#ifdef TTY_PERM_INVENT
+#include "wintty.h"     /* just for define of NHW_TTYINVENT */
+#endif
+
 static void moveloop_preamble(boolean);
 static void u_calc_moveamt(int);
 #ifdef POSITIONBAR
@@ -631,6 +635,11 @@ display_gamewindows(void)
        ever having been used, use it here to pacify the Qt interface */
     start_menu(WIN_INVEN, 0U), end_menu(WIN_INVEN, (char *) 0);
 
+#ifdef TTY_PERM_INVENT
+    if (WINDOWPORT("tty") && iflags.perm_invent) {
+        g.tty_invent_win = create_nhwindow(NHW_TTYINVENT);
+    }
+#endif
 #ifdef MAC
     /* This _is_ the right place for this - maybe we will
      * have to split display_gamewindows into create_gamewindows
@@ -650,6 +659,10 @@ display_gamewindows(void)
     display_nhwindow(WIN_MESSAGE, FALSE);
     clear_glyph_buffer();
     display_nhwindow(WIN_MAP, FALSE);
+#ifdef TTY_PERM_INVENT
+    if (g.tty_invent_win != WIN_ERR)
+        display_nhwindow(g.tty_invent_win, FALSE);
+#endif
 }
 
 void
index 9879d0f4d930320deb2f6f8cf05eac683ba07585..f0c032d05a1f1e2e0af5e1437684d5035dedf77c 100644 (file)
@@ -435,6 +435,9 @@ const struct instance_globals g_init = {
     NULL, /* invbuf */
     0, /* inbufsize */
     WIN_ERR, /* cached_pickinv_win */
+#ifdef TTY_PERM_INVENT
+    WIN_ERR, /* tty_invent_win */
+#endif
     0, /* this_type */
     NULL, /* this_title */
     UNDEFINED_VALUES, /* only (coord) */
index da0dd7602b70fc3c0d9b4a458a57bfeb821d5c65..8cd30df0287408478d5f8f7f55beba9633b3985c 100644 (file)
@@ -1507,9 +1507,11 @@ docrt(void)
     register int x, y;
     register struct rm *lev;
 
-    if (!u.ux)
+    if (!u.ux || g.program_state.in_docrt)
         return; /* display isn't ready yet */
 
+    g.program_state.in_docrt = TRUE;
+
     if (u.uswallow) {
         swallowed(1);
         goto post_map;
@@ -1552,6 +1554,7 @@ docrt(void)
     update_inventory();
 
     g.context.botlx = 1; /* force a redraw of the bottom line */
+    g.program_state.in_docrt = FALSE;
 }
 
 /* for panning beyond a clipped region; resend the current map data to
index 3f34e20dfbc601d697ccbff778768f673fd784fb..ec8886fcff83854b895735e7a2fd9badb4344bef 100644 (file)
@@ -109,6 +109,9 @@ extern boolean colors_changed;  /* in tos.c */
 extern char *shade[3];          /* in sys/msdos/video.c */
 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
 #endif
+#ifdef TTY_PERM_INVENT
+extern void tty_perm_invent_toggled(boolean negated);
+#endif
 
 static char empty_optstr[] = { '\0' };
 boolean duplicate, using_alias;
@@ -4467,6 +4470,10 @@ optfn_boolean(int optidx, int req, boolean negated, char *opts, char *op)
         case opt_use_inverse:
         case opt_hilite_pile:
         case opt_perm_invent:
+#ifdef TTY_PERM_INVENT
+            if (WINDOWPORT("tty"))
+                tty_perm_invent_toggled(negated);
+#endif
         case opt_ascii_map:
         case opt_tiled_map:
             g.opt_need_redraw = TRUE;
index 1ee0ffda0fdb58b489c9e6c8ed9c6b101f39d5ba..bc2927e44b5a4398c0765d4ae94dbf9ba8ba53a9 100644 (file)
@@ -2364,13 +2364,18 @@ void nethack_enter_consoletty(void)
                      console.orig_csbi.srWindow.Left + 1;
     console.Width = max(console.Width, COLNO);
 #else
-    console.width = COLNO;
+//    console.width = COLNO;
+    console.width = console.orig_csbi.srWindow.Right -
+                     console.orig_csbi.srWindow.Left + 1;
+    if (console.width < COLNO)
+        console.width = COLNO;
 #endif
 
     console.height = console.orig_csbi.srWindow.Bottom -
                      console.orig_csbi.srWindow.Top + 1;
-    console.height = max(console.height, ROWNO + 3);
-
+//    console.height = max(console.height, ROWNO + 3);
+    if (console.height < (ROWNO + 2 + 1))
+        console.height = (ROWNO + 2 + 1);
     console.buffer_size = console.width * console.height;
 
 
index 4b61ee019fda54713f456bc547b21c456bc4a209..bebd22fdf9cb17d32eea60330b33ac813a2ba79a 100644 (file)
@@ -161,6 +161,12 @@ synch_cursor(void)
 {
     return;
 }
+#ifdef TTY_PERM_INVENT
+void
+tty_perm_invent_toggled(boolean negated)
+{
+}
+#endif
 #endif
 
 void
index dc7560e63d6b1a5fbf7c47c29762987ebf10d4cd..997b435456b225f11ba1670f37020cad7f462944 100644 (file)
@@ -100,6 +100,9 @@ extern void msmsg(const char *, ...);
 struct window_procs tty_procs = {
     "tty",
     (0
+#ifdef TTY_PERM_INVENT
+     | WC_PERM_INVENT
+#endif
 #ifdef MSDOS
      | WC_TILED_MAP | WC_ASCII_MAP
 #endif
@@ -248,6 +251,15 @@ static void status_sanity_check(void);
 void g_pututf8(uint8 *utf8str);
 #endif
 
+#ifdef TTY_PERM_INVENT
+void tty_perm_invent_toggled(boolean negated);
+static void tty_invent_box_glyph_init(struct WinDesc *cw);
+static boolean calling_from_update_inventory = FALSE;
+struct tty_perminvent_cell zerottycell = { 0, 0, 0, 0, { 0 } };
+enum { border_left, border_middle, border_right, border_elements };
+static int bordercol[border_elements] = { 0, 0, 0 }; /* left, middle, right */
+#endif
+
 /*
  * A string containing all the default commands -- to add to a list
  * of acceptable inputs.
@@ -525,6 +537,12 @@ tty_preference_update(const char *pref)
     consoletty_preference_update(pref);
 #else
     genl_preference_update(pref);
+#endif
+#ifdef TTY_PERM_INVENT
+    if (!strcmp(pref, "symset") && iflags.window_inited) {
+       if (g.tty_invent_win != WIN_ERR)
+           tty_invent_box_glyph_init(wins[g.tty_invent_win]);
+    }
 #endif
     return;
 }
@@ -1567,6 +1585,99 @@ tty_create_nhwindow(int type)
         newwin->cols = ttyDisplay->cols;
         newwin->maxrow = newwin->maxcol = 0;
         break;
+#ifdef TTY_PERM_INVENT
+    case NHW_TTYINVENT:
+        /* Is there enough real estate to do this beyond the status line?
+         * Rows:
+         * Top border line (1)
+         * 26 inventory rows (26)
+         * Bottom border line (1)
+         * 1 + 26 + 1 = 28
+         *
+         * Cols:
+         * Left border (1)
+         * Left inventory items (38)
+         * Middle separation (1)
+         * Right inventory items (38)
+         * Right border (1)
+         * 1 + 38 + 1 + 38 + 1 = 79
+         *
+         * The topline + map rows + status lines require:
+         * 1 + 21 + 2 (or 3) = 24 (or 25 depending on status line count).
+         * So we can only present a full inventory on tty if there are
+         * 28 + 24 (or 25) available (52 or 53 rows on the terminal).
+         * Correspondingly ttyDisplay->rows has to be at least 52 (or 53).
+         *
+         */
+        newwin->offx = 0;
+        /* topline + map rows + status lines */
+        newwin->offy = 1 + ROWNO + ((iflags.wc2_statuslines > 2) ? 3 : 2);
+        newwin->rows = (ttyDisplay->rows - newwin->offy) - 1;
+        newwin->cols = ttyDisplay->cols;
+        newwin->maxrow = 0;
+        newwin->maxcol = 79;  /* bhaak */
+        /* these weren't initialized as of yet, and as such could
+           be non-zero which would cause tty_destroy_window()
+           and friends to try and free non-malloc'd memory */
+        newwin->data = (char **) 0;
+        newwin->datlen = (short *) 0;
+        newwin->cells = (struct tty_perminvent_cell **) 0;
+
+        if (newwin->rows < tty_pi_minrow) {
+            tty_destroy_nhwindow(newid);
+            raw_printf("tty perm_invent has been disabled.");
+            raw_printf(
+                "tty perm_invent requires %d rows, your terminal has %d.",
+                (iflags.wc2_statuslines > 2) ? 54 : 53, ttyDisplay->rows);
+            iflags.perm_invent = FALSE;
+            return WIN_ERR;
+        } else if (newwin->cols < tty_pi_mincol) {
+            tty_destroy_nhwindow(newid);
+            raw_printf("tty perm_invent has been disabled.");
+            raw_printf(
+                "tty perm_invent requires %d columns, your terminal has %d.",
+                tty_pi_mincol, ttyDisplay->cols);
+            iflags.perm_invent = FALSE;
+            return WIN_ERR;
+        } else {
+            int r, c;
+
+            newwin->maxrow = tty_pi_minrow;
+            newwin->maxcol = newwin->cols;
+            /* establish the borders */
+            bordercol[border_left] = 0;
+            bordercol[border_middle] = ( newwin->maxcol / 2) + 1;
+            bordercol[border_right] = newwin->maxcol - 1;
+
+            if (newwin->maxrow) {
+                newwin->cells = (struct tty_perminvent_cell **) alloc(
+                    (unsigned) (newwin->maxrow
+                                * sizeof(struct tty_perminvent_cell *)));
+                for (i = 0; i < newwin->maxrow; i++) {
+                    if (newwin->maxcol) {
+                        newwin->cells[i] = (struct tty_perminvent_cell *) alloc(
+                            (unsigned) (newwin->maxcol
+                                * sizeof(struct tty_perminvent_cell)));
+                    }
+                }
+            }
+
+            for (r = 0; r < newwin->maxrow; r++)
+                for (c = 0; c < newwin->maxcol; c++) {
+                    newwin->cells[r][c] = zerottycell;
+                    if (r == 0 || (newwin->maxrow - 1)
+                               || c == bordercol[border_left]
+                               || c == bordercol[border_middle]
+                               || c == bordercol[border_right]) {
+                        newwin->cells[r][c].content.gi = (glyph_info *) alloc(
+                                                    (unsigned) sizeof(glyph_info));
+                    }
+                }
+            return newid;
+        }
+        /*NOTREACHED*/
+        break;
+#endif
     default:
         panic("Tried to create window type %d\n", (int) type);
         /*NOTREACHED*/
@@ -2571,7 +2682,30 @@ tty_destroy_nhwindow(winid window)
         iflags.window_inited = 0;
     if (cw->type == NHW_MAP)
         clear_screen();
-
+#ifdef TTY_PERM_INVENT
+    if (cw->type == NHW_TTYINVENT) {
+        int r, c;
+
+        if (cw->cells) {
+            for (r = 0; r < cw->maxrow; r++)
+                for (c = 0; c < cw->maxcol; c++) {
+                    if (cw->cells[r][c].glyph)
+                        free((genericptr_t) cw->cells[r][c].content.gi);
+                    cw->cells[r][c] = zerottycell;
+                }
+            for (r = 0; r < cw->maxrow; r++)
+                if (cw->cells[r]) {
+                    free((genericptr_t) cw->cells[r]);
+                    cw->cells[r] = (struct tty_perminvent_cell *) 0;
+                }
+            free((genericptr_t) cw->cells);
+            cw->cells = (struct tty_perminvent_cell **) 0;
+            cw->rows = cw->cols = 0;
+        }
+        cw->maxrow = cw->maxcol = 0;
+        g.tty_invent_win = WIN_ERR;
+    }
+#endif
     free_window_info(cw, TRUE);
     free((genericptr_t) cw);
     wins[window] = 0; /* available for re-use */
@@ -2692,6 +2826,9 @@ tty_putsym(winid window, int x, int y, char ch)
     switch (cw->type) {
 #ifndef STATUS_HILITES
     case NHW_STATUS:
+#endif
+#ifdef TTY_PERM_INVENT
+    case NHW_TTYINVENT:
 #endif
     case NHW_MAP:
     case NHW_BASE:
@@ -2761,7 +2898,11 @@ tty_putstr(winid window, int attr, const char *str)
     if (str == (const char *) 0
         || ((cw->flags & WIN_CANCELLED) && (cw->type != NHW_MESSAGE)))
         return;
-    if (cw->type != NHW_MESSAGE)
+    if (cw->type != NHW_MESSAGE
+#ifdef TTY_PERM_INVENT
+&& window != g.tty_invent_win
+#endif
+       )
         str = compress_str(str);
 
     ttyDisplay->lastwin = window;
@@ -3290,14 +3431,241 @@ tty_message_menu(char let, int how, const char *mesg)
     return ((how == PICK_ONE && morc == let) || morc == '\033') ? morc : '\0';
 }
 
+#ifdef TTY_PERM_INVENT
+static boolean done_box_init = FALSE;
+DISABLE_WARNING_FORMAT_NONLITERAL
+#endif
+
 /* update persistent inventory window */
 void
 tty_update_inventory(int arg UNUSED)
 {
-    /* tty doesn't support persistent inventory window */
+#ifdef TTY_PERM_INVENT
+    int row, col, pass, ccnt;
+    struct WinDesc *cw = 0;
+    winid window = g.tty_invent_win;
+    struct obj *obj;
+    char invbuf[BUFSZ], *text, null[1] = {'\0'};
+    boolean force_redraw = g.program_state.in_docrt ? TRUE
+                            : FALSE;
+    struct tty_perminvent_cell *cell;
+
+/*
+          1         2         3         4         5         6         7
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+x                                       x                                     x
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+    /* we just return if the window creation failed, probably due to
+       not meeting size requirements */
+    if (window == WIN_ERR || !iflags.perm_invent)
+        return;
+
+    if ((cw = wins[window]) == (struct WinDesc *) 0)
+        panic(winpanicstr, window);
+
+    if (!done_box_init) {
+        tty_invent_box_glyph_init(cw);
+    }
+
+    obj = g.invent;
+    text = null;
+    ccnt = 0;
+    if (obj) {
+        if (obj->invlet == '$')
+            obj = obj->nobj;
+        if (obj) {
+            Snprintf(invbuf, sizeof invbuf, "%c - %s", obj->invlet,
+                     doname(obj));
+            text = invbuf;
+        }
+    }
+    for (pass = 0; pass < 2; ++pass) {
+        for (row = 1; row < (cw->maxrow - 1); ++row) { /* row below top border */
+            for (col = (pass
+                            ? bordercol[border_middle] + 1
+                            : bordercol[border_left] + 1);
+                 col < (pass
+                            ? bordercol[border_right]
+                            : bordercol[border_middle]); ++col) {
+                cell = &cw->cells[row][col];
+                if (obj && *text && ccnt < (bordercol[border_middle] - 1)) {
+                    if (cell->content.ttychar != *text)
+                        cell->refresh = 1;
+                    cell->content.ttychar = *text;
+                    text++;
+                    ccnt++;
+                } else {
+                    if (cell->content.ttychar != ' ')
+                        cell->refresh = 1;
+                    cell->content.ttychar = ' ';
+                }
+                cell->text = 1;
+                cell->glyph = 0;
+            }
+            if (obj) {
+                obj = obj->nobj;
+                if (obj) {
+                    if (obj->invlet == '$')
+                        obj = obj->nobj;
+                    if (obj) {
+                        Snprintf(invbuf, sizeof invbuf, "%c - %s",
+                                 obj->invlet, doname(obj));
+                        text = invbuf;
+                        ccnt = 0;
+                    }
+                }
+            } else {
+                text = null;
+            }
+        }
+    }
+    /* now render to the display */
+    for (row = 0; row < cw->maxrow; ++row)
+        for (col = 0; col < cw->maxcol; ++col) {
+            cell = &cw->cells[row][col];
+            if (cell->refresh || force_redraw) {
+                if (cell->glyph) {
+                    tty_print_glyph(window, col + 1, row,
+                                    cell->content.gi,
+                                    &nul_glyphinfo);
+                    end_glyphout();
+                } else {
+                    if (col != cw->curx || row != cw->cury)
+                        tty_curs(window, col + 1, row);
+                    (void) putchar(cell->content.ttychar);
+                    ttyDisplay->curx++;
+                    cw->curx++;
+                }
+                cell->refresh = 0;
+            }
+        }
+#endif
     return;
 }
 
+#ifdef TTY_PERM_INVENT
+
+void
+tty_refresh_inventory(int start, int stop, int y)
+{
+    int row = y, col, col_limit = stop;
+    struct WinDesc *cw = 0;
+    winid window = g.tty_invent_win;
+    struct tty_perminvent_cell *cell;
+
+    if (window == WIN_ERR || !iflags.perm_invent || y < 0)
+        return;
+
+    if ((cw = wins[window]) == (struct WinDesc *) 0)
+        panic(winpanicstr, window);
+
+    if (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 */
+    for (col = start - 1; col < col_limit; ++col) {
+        cell = &cw->cells[row][col];
+        if (cell->glyph) {
+            tty_print_glyph(window, col + 1, row, cell->content.gi,
+                            &nul_glyphinfo);
+            end_glyphout();
+        } else {
+            if (col != cw->curx || row != cw->cury)
+                tty_curs(window, col + 1, row);
+            (void) putchar(cell->content.ttychar);
+            ttyDisplay->curx++;
+            cw->curx++;
+        }
+        cell->refresh = 0;
+    }
+}
+
+static void tty_invent_box_glyph_init(struct WinDesc *cw)
+{
+    int row, col, glyph;
+    struct tty_perminvent_cell *cell;
+
+/*
+          1         2         3         4         5         6         7
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+x                                       x                                     x
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+
+    for (row = 0; row < cw->maxrow; ++row)
+        for (col = 0; col < cw->maxcol; ++col) {
+            cell = &cw->cells[row][col];
+            glyph = 0;
+            if (row == 0) {
+                if (col == bordercol[border_left])
+                    glyph = cmap_to_glyph(S_tlcorn);
+                else if ((col > bordercol[border_left] && col < bordercol[border_middle])
+                         || (col > bordercol[border_middle]
+                             && col < bordercol[border_right]))
+                    glyph = cmap_to_glyph(S_hwall);
+                else if (col == bordercol[border_middle])
+                    glyph = cmap_to_glyph(S_tdwall);
+                else if (col == bordercol[border_right])
+                    glyph = cmap_to_glyph(S_trcorn);
+            } else if (row == (cw->maxrow - 1)) {
+                if (col == bordercol[border_left])
+                    glyph = cmap_to_glyph(S_blcorn);
+                else if ((col > bordercol[border_left] && col < bordercol[border_middle])
+                         || (col > bordercol[border_middle]
+                             && col < bordercol[border_right]))
+                    glyph = cmap_to_glyph(S_hwall);
+                else if (col == bordercol[border_middle])
+                    glyph = cmap_to_glyph(S_tuwall);
+                else if (col == bordercol[border_right])
+                    glyph = cmap_to_glyph(S_brcorn);
+            } else {
+                if (col == bordercol[border_left]
+                    || col == bordercol[border_middle]
+                    || col == bordercol[border_right])
+                    glyph = cmap_to_glyph(S_vwall);
+            }
+            if (glyph) {
+                int oldsymidx = cell->content.gi->gm.sym.symidx;
+#ifdef ENHANCED_SYMBOLS
+                struct unicode_representation *oldgmu =
+                    cell->content.gi->gm.u;
+#endif
+                map_glyphinfo(0, 0, glyph, 0, cell->content.gi);
+                if (
+#ifdef ENHANCED_SYMBOLS
+                    cell->content.gi->gm.u != oldgmu ||
+#endif
+                    cell->content.gi->gm.sym.symidx != oldsymidx)
+                    cell->refresh = 1;
+                cell->glyph = 1;
+                cell->text = 0;
+            }
+        }
+    done_box_init = TRUE;
+}
+
+RESTORE_WARNING_FORMAT_NONLITERAL
+
+void
+tty_perm_invent_toggled(boolean negated)
+{
+    if (negated) {
+        destroy_nhwindow(g.tty_invent_win), g.tty_invent_win = WIN_ERR;
+        done_box_init = FALSE;
+    } else {
+        if (WINDOWPORT("tty")) {
+            g.tty_invent_win = create_nhwindow(NHW_TTYINVENT);
+            if (g.tty_invent_win != WIN_ERR)
+                display_nhwindow(g.tty_invent_win, FALSE);
+        }
+    }
+}
+#endif
+
 void
 tty_mark_synch(void)
 {
@@ -3357,6 +3725,14 @@ docorner(register int xmin, register int ymax)
     for (y = 0; y < ymax; y++) {
         tty_curs(BASE_WINDOW, xmin, y); /* move cursor */
         cl_end();                       /* clear to end of line */
+#ifdef TTY_PERM_INVENT
+        /* the whole thing is beyond the board */
+        if (g.tty_invent_win != WIN_ERR && WINDOWPORT("tty")) {
+            struct WinDesc *icw = wins[g.tty_invent_win];
+            tty_refresh_inventory(xmin - (int) icw->offx, icw->maxcol,
+                                  y - (int) icw->offy);
+        }
+#endif
 #ifdef CLIPPING
         if (y < (int) cw->offy || y + clipy > ROWNO)
             continue; /* only refresh board */
@@ -3373,6 +3749,7 @@ docorner(register int xmin, register int ymax)
             continue; /* only refresh board  */
         row_refresh(xmin - (int) cw->offx, COLNO - 1, y - (int) cw->offy);
 #endif
+
     }
 
     end_glyphout();
@@ -3505,11 +3882,7 @@ tty_cliparound(int x, int y)
 
 void
 tty_print_glyph(winid window, xchar x, xchar y,
-#if defined(TTY_TILES_ESCCODES) || defined(MSDOS)
                 const glyph_info *glyphinfo,
-#else
-                const glyph_info *glyphinfo UNUSED,
-#endif
                 const glyph_info *bkglyphinfo UNUSED)
 {
     boolean inverse_on = FALSE, colordone = FALSE, glyphdone = FALSE;
@@ -3555,6 +3928,9 @@ tty_print_glyph(winid window, xchar x, xchar y,
         /* we don't link with termcap.o if NO_TERMS is defined */
         if ((tty_procs.wincap2 & WC2_U_24BITCOLOR) && SYMHANDLING(H_UTF8)
             && iflags.colorcount >= 256
+#ifdef TTY_PERM_INVENT
+            && !calling_from_update_inventory
+#endif
             && glyphinfo->gm.u && glyphinfo->gm.u->ucolor) {
             term_start_24bitcolor(glyphinfo->gm.u);
             color24bit_on = TRUE;