From: nhmall Date: Fri, 24 Jun 2022 19:01:38 +0000 (-0400) Subject: move some parts of TTY_PERM_INVENT into core X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18b28084f87fe6a20afb3b7c6211d8217d3ee679;p=nethack move some parts of TTY_PERM_INVENT into core This starts the tty perm_invent just in time later in the startup rather than initializing it with the other game windows. This also splits the duties: The core will inquire from the window port about how many inventory slots it can fill. The core will handle figuring out the inventory text and inventory letters, and will do the traversing of internal data structures like obj chains, and passing customization options on to the window port. The window port will look after placing each inventory slot's text at an appropriate location on the screen. This, in theory, makes the core-portion available for window ports other than tty to use, though none currently do. The decision of what goes in an inventory slot is all left up to the core with the update_invent_slot interface. Documentation updates will come later, not at this time. --- diff --git a/include/decl.h b/include/decl.h index 67598d852..c66a98c11 100644 --- a/include/decl.h +++ b/include/decl.h @@ -972,9 +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 + winid perm_invent_win; + int core_invent_state; + /* 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 */ diff --git a/include/extern.h b/include/extern.h index f9525d6fd..e3ebc56ef 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1174,6 +1174,7 @@ extern long count_contents(struct obj *, boolean, boolean, boolean, boolean); extern void carry_obj_effects(struct obj *); extern const char *currency(long); extern void silly_thing(const char *, struct obj *); +extern void core_update_invent_slot(void); /* ### ioctl.c ### */ diff --git a/include/wintty.h b/include/wintty.h index 552684d4c..39f8dddd9 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -11,6 +11,7 @@ #define WINDOW_STRUCTS #ifdef TTY_PERM_INVENT + enum { tty_pi_minrow = 28, tty_pi_mincol = 79 }; /* for static init of zerottycell, put pointer first */ union ttycellcontent { @@ -123,11 +124,7 @@ struct tty_status_fields { #ifdef NHW_BASE #undef NHW_BASE #endif -#define NHW_BASE (NHW_TEXT + 1) - -#ifdef TTY_PERM_INVENT -#define NHW_TTYINVENT (NHW_BASE + 1) -#endif +#define NHW_BASE (NHW_LAST_TYPE + 1) extern struct window_procs tty_procs; diff --git a/include/wintype.h b/include/wintype.h index e262b1aa9..010ea2dbb 100644 --- a/include/wintype.h +++ b/include/wintype.h @@ -111,6 +111,8 @@ typedef struct gi { #define NHW_MAP 3 #define NHW_MENU 4 #define NHW_TEXT 5 +#define NHW_PERMINVENT 6 +#define NHW_LAST_TYPE NHW_PERMINVENT /* attribute types for putstr; the same as the ANSI value, for convenience */ #define ATR_NONE 0 @@ -162,19 +164,37 @@ typedef struct gi { #define MENU_BEHAVE_STANDARD 0x0000000U +/* inventory modes */ +enum inv_modes { InvNormal = 0, InvShowGold = 1, InvSparse = 2, InvInUse = 4 }; + +enum to_core_flags { + active = 0x001, + prohibited = 0x002, + no_init_done = 0x004 +}; + +enum from_core_requests { + request_settings = 1, + update_slot = 2, + render = 3 +}; + struct to_core { + long tocore_flags; boolean active; boolean use_update_inventory; /* disable the newer slot interface */ - int slotcount; - int low_slot_num, high_slot_num; - int max_slot_text; + int maxslot; + int needrows, needcols; + int haverows, havecols; }; struct from_core { - long piflags; - int slot; /* which inventory slot; 0 means info exchange only */ + enum from_core_requests core_request; + enum inv_modes invmode; + boolean force_redraw; + int slot; /* which inventory slot; 0 indicates request */ int invlet; - const char *text; /* the text to display */ + char text[BUFSZ]; }; struct perminvent_info_t { @@ -184,6 +204,8 @@ struct perminvent_info_t { typedef struct perminvent_info_t perminvent_info; +#define CORE_INVENT + /* clang-format on */ #endif /* WINTYPE_H */ diff --git a/src/allmain.c b/src/allmain.c index a39f5d216..c255ba18a 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -12,10 +12,6 @@ #include #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 @@ -635,11 +631,6 @@ 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 @@ -659,11 +650,7 @@ 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 newgame(void) diff --git a/src/decl.c b/src/decl.c index f0c032d05..f72478632 100644 --- a/src/decl.c +++ b/src/decl.c @@ -435,9 +435,8 @@ 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 + WIN_ERR, /* perm_invent_win */ + 0, /* core_invent_state */ 0, /* this_type */ NULL, /* this_title */ UNDEFINED_VALUES, /* only (coord) */ diff --git a/src/invent.c b/src/invent.c index 7d3677b41..44090afe0 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2429,9 +2429,13 @@ update_inventory(void) */ save_suppress_price = iflags.suppress_price; iflags.suppress_price = 0; - - (*windowprocs.win_update_inventory)(0); - +#if defined(TTY_PERM_INVENT) && defined(CORE_INVENT) + if (WINDOWPORT("tty")) + core_update_invent_slot(); + else +#else + (*windowprocs.win_update_inventory)(0); +#endif iflags.suppress_price = save_suppress_price; } @@ -5333,4 +5337,188 @@ display_binventory(int x, int y, boolean as_if_seen) return n; } +#if defined(CORE_INVENT) +/* enum and structs are defined in wintype.h */ +static perminvent_info zeropi = { 0 }; +static perminvent_info pi_info; +static int invmode = InvNormal; +static char Empty[1] = { '\0' }; +#ifdef TTY_PERM_INVENT +extern void tty_perm_invent_toggled(boolean negated); +#endif + +void +core_update_invent_slot() +{ + static perminvent_info *pi = 0; + char *text, nxtlet; + int slot; + boolean show_gold = (invmode & InvShowGold) != 0, + inuse_only = (invmode & InvInUse) != 0, + sparse = (invmode & InvSparse) != 0; + const char *wport_id; + struct obj *obj; + + if (g.perm_invent_win == WIN_ERR && g.core_invent_state) + return; + + if (!iflags.perm_invent && g.core_invent_state) { + /* Odd - but this could be end-of-game disclosure + * which just sets boolean iflag.perm_invent to + * FALSE without actually doing anything else. + */ +#ifdef TTY_PERM_INVENT + if (WINDOWPORT("tty")) + tty_perm_invent_toggled(TRUE); /* TRUE means negated */ +#endif + (void) doredraw(); + return; + } + + /* + * The core looks after what content goes into the + * inventory slots, and deals with things like obj + * chains etc, so the window port doesn't have to. + * + * The window port informs the core of the number of + * slots that it will process. + * + * The core tells the window port what the contents of the + * inventory slots should be. + * + * The core requests the window port when to render, after + * all the content has been updated. + * + * The window port looks after the placement of an inventory + * slot's contents onto the display in an appropriate fashion, + * The core doesn't care, and leaves that up to the window port. + * + * The core slot handling is no longer tied to TTY_PERM_INVENT, + * although at this point that's the only window port to utilize + * it. The rest are still rolling their own via the basic + * [port]_update_inventory() mechanism. + */ + + if (WINDOWPORT("tty") && iflags.perm_invent) + wport_id = "tty perm_invent"; + else + wport_id = "perm_invent"; + + pi_info.fromcore.core_request = 0; + if (!g.core_invent_state) { + { + /*TEMPORARY*/ + char *envtmp = nh_getenv("TTYINV"); + invmode = envtmp ? atoi(envtmp) : InvNormal; + } + pi_info.fromcore.invmode = invmode; + pi_info = zeropi; + /* Send the wport a request to get the related settings. */ + pi_info.fromcore.core_request = request_settings; + if ((pi = update_invent_slot(g.perm_invent_win, (slot = 0), &pi_info))) { + if ((pi->tocore.tocore_flags & prohibited) != 0) { + /* sizes aren't good enough */ + set_option_mod_status("perm_invent", set_gameview); + iflags.perm_invent = FALSE; + pline("%s could not be enabled.", wport_id); + pline("%s needs a terminal that is at least %dx%d, yours is %dx%d.", + wport_id, + pi->tocore.needrows, pi->tocore.needcols, + pi->tocore.haverows, pi->tocore.havecols); + wait_synch(); + return; + } + } + g.perm_invent_win = create_nhwindow(NHW_PERMINVENT); + if (g.perm_invent_win == WIN_ERR) + return; + display_nhwindow(g.perm_invent_win, FALSE); + g.core_invent_state++; + } + text = Empty; /* lint suppression */ + pi_info.fromcore.core_request = update_slot; + pi_info.fromcore.force_redraw = g.program_state.in_docrt ? TRUE : FALSE, + + obj = g.invent; + for (slot = 0; slot < pi->tocore.maxslot; ++slot) { + nxtlet = '?'; /* always gets set to something else if actually used */ + if (!sparse) { + while (obj && ((obj->invlet == GOLD_SYM && !show_gold) + || (!obj->owornmask && inuse_only))) + obj = obj->nobj; + } else { + if (!show_gold) + nxtlet = (slot < 26) ? ('a' + slot) : ('A' + slot - 26); + else + nxtlet = (slot == 0) ? GOLD_SYM + : (slot < 27) ? ('a' + slot - 1) + : (slot < 53) ? ('A' + slot - 27) + : NOINVSYM; + for (obj = g.invent; obj; obj = obj->nobj) + if (obj->invlet == nxtlet) + break; + } + if (obj) { + /* TODO: check for MENUCOLORS match */ + text = doname(obj); /* 'text' will switch to fromcore.text below */ + /* strip away "a"/"an"/"the" prefix to show a bit more of the + interesting part of the object's description; + this is inline version of pi_article_skip() from cursinvt.c; + should move that to hacklib.c and use it here */ + if (text[0] == 'a') { + if (text[1] == ' ') + text += 2; + else if (text[1] == 'n' && text[2] == ' ') + text += 3; + } else if (text[0] == 't') { + if (text[1] == 'h' && text[2] == 'e' && text[3] == ' ') + text += 4; + } + Snprintf(pi_info.fromcore.text, + sizeof pi_info.fromcore.text, + "%c - %s", obj->invlet, text); + text = pi_info.fromcore.text; + obj = obj->nobj; /* set up for next iteration */ + } else if (sparse) { + Sprintf(pi_info.fromcore.text, "%c", nxtlet); /* empty slot */ + text = pi_info.fromcore.text; + } else { + if (slot == 0) { + Sprintf(pi_info.fromcore.text, "%-4s[%s]", "", + !g.invent ? "empty" + : inuse_only ? "no items are in use" + : "only gold"); + text = pi_info.fromcore.text; + } else { + text = Empty; /* "" => fill slot with spaces */ + } + } + if (!*text) + pi_info.fromcore.text[0] = Empty[0]; + pi = update_invent_slot(g.perm_invent_win, slot + 1, &pi_info); + } + pi_info.fromcore.force_redraw = g.program_state.in_docrt ? TRUE : FALSE, + pi_info.fromcore.core_request = render; + pi = update_invent_slot(g.perm_invent_win, (slot = 0), &pi_info); +} + +#if 0 +RESTORE_WARNING_FORMAT_NONLITERAL + +void +tty_perm_invent_toggled(boolean negated) +{ + if (negated) { + if (g.perm_invent_win != WIN_ERR) + destroy_nhwindow(g.perm_invent_win), g.perm_invent_win = WIN_ERR; + done_tty_perm_invent_init = FALSE; + } else { + g.perm_invent_win = create_nhwindow(NHW_PERMINVENT); + if (g.perm_invent_win != WIN_ERR) + display_nhwindow(g.perm_invent_win, FALSE); + } +} +#endif +#endif /* CORE_INVENT */ + /*invent.c*/ diff --git a/src/options.c b/src/options.c index edcc6b8bc..71dd7258d 100644 --- a/src/options.c +++ b/src/options.c @@ -4417,7 +4417,7 @@ optfn_boolean(int optidx, int req, boolean negated, char *opts, char *op) -> tty_create_nhwindow(WIN_TTYINVENT) -> tty_create_invent() gives feedback for failure (terminal too small) */ - if (g.tty_invent_win == WIN_ERR) + if (g.perm_invent_win == WIN_ERR) return optn_silenterr; } #endif diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 193aada84..89ad5baeb 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -255,15 +255,25 @@ void g_pututf8(uint8 *utf8str); #ifdef TTY_PERM_INVENT void tty_perm_invent_toggled(boolean negated); -static int ttyinv_create_window(int, struct WinDesc *); -static void tty_invent_box_glyph_init(struct WinDesc *cw); -static boolean calling_from_update_inventory = FALSE; static struct tty_perminvent_cell zerottycell = { 0, 0, 0, 0, { 0 } }; static glyph_info zerogi = { 0 }; +#ifdef CORE_INVENT +static struct to_core zero_tocore = { 0 }; +#endif enum { border_left, border_middle, border_right, border_elements }; static int bordercol[border_elements] = { 0, 0, 0 }; /* left, middle, right */ -enum { InvNormal = 0, InvShowGold = 1, InvSparse = 2, InvInUse = 4 }; -static int ttyinvmode = InvNormal; +static int ttyinvmode = InvNormal; /* enum is in wintype.h */ +static boolean done_tty_perm_invent_init = FALSE; +#ifndef NOINVSYM /* invent.c */ +#define NOINVSYM '#' +#endif +static int ttyinv_create_window(int, struct WinDesc *); + +static void tty_invent_box_glyph_init(struct WinDesc *cw); +static boolean calling_from_update_inventory = FALSE; +static boolean assesstty(enum inv_modes, short *, short *, + long *, long *, long *, long *, long *); +static void ttyinv_populate_slot(struct WinDesc *, int, int, const char *); #endif /* @@ -551,8 +561,8 @@ tty_preference_update(const char *pref) only might individual symbols change (punctuation vs line drawing), the way to render them might change too (Handling: DEC/UTF8/&c) */ if (!strcmp(pref, "symset") && iflags.window_inited) { - if (g.tty_invent_win != WIN_ERR) - tty_invent_box_glyph_init(wins[g.tty_invent_win]); + if (g.perm_invent_win != WIN_ERR) + tty_invent_box_glyph_init(wins[g.perm_invent_win]); } #endif return; @@ -1597,12 +1607,7 @@ tty_create_nhwindow(int type) newwin->maxrow = newwin->maxcol = 0; break; #ifdef TTY_PERM_INVENT - case NHW_TTYINVENT: - { - /*TEMPORARY*/ - char *envtmp = nh_getenv("TTYINV"); - ttyinvmode = envtmp ? atoi(envtmp) : InvNormal; - } + case NHW_PERMINVENT: return ttyinv_create_window(newid, newwin); #endif default: @@ -1640,7 +1645,8 @@ tty_create_nhwindow(int type) static int ttyinv_create_window(int newid, struct WinDesc *newwin) { - int i, r, c, minrow; + int i, r, c; + long minrow; /* long to match maxrow declaration */ unsigned n; /* Is there enough real estate to do this beyond the status line? @@ -1668,37 +1674,20 @@ ttyinv_create_window(int newid, struct WinDesc *newwin) * them would reduce the number of rows needed by 2.] * */ - newwin->offx = 0; - /* topline + map rows + status lines */ - newwin->offy = 1 + ROWNO + 3; /* 3: + 2 + (iflags.wc2_statuslines > 2) */ - newwin->rows = (ttyDisplay->rows - newwin->offy); - newwin->cols = ttyDisplay->cols; - newwin->maxrow = 0; - newwin->maxcol = 79; /* bhaak */ + /* preliminary init in case tty_desctroy_nhwindow() gets called */ newwin->data = (char **) 0; newwin->datlen = (short *) 0; newwin->cells = (struct tty_perminvent_cell **) 0; - minrow = tty_pi_minrow; - if ((ttyinvmode & InvShowGold) != 0) - minrow += 1; - /* "normal" max for items in use would be 3 weapon + 7 armor + 4 - accessories == 14, but being punished and picking up the ball will - add 1, and some quest artifacts have an an #invoke property that's - tracked via obj->owornmask so could add more; if hero ends up with - more than 15 in-use items, some will be left out; - Qt's "paper doll" adds first lit lamp/candle and first active - leash; those aren't tracked via owornmask so we don't notice them */ - if ((ttyinvmode & InvInUse) != 0) - minrow = 1 + 15 + 1; /* top border + 15 lines + bottom border */ - - if (newwin->rows < minrow || newwin->cols < tty_pi_mincol) { - tty_destroy_nhwindow(newid); /* sets g.tty_invent_win to WIN_ERR */ + if (!assesstty(ttyinvmode, + &newwin->offx, &newwin->offy, &newwin->rows, &newwin->cols, + &newwin->maxcol, &minrow, &newwin->maxrow)) { + tty_destroy_nhwindow(newid); /* sets g.perm_invent_win to WIN_ERR */ pline("%s.", "tty perm_invent could not be enabled"); pline( "tty perm_invent needs a terminal that is at least %dx%d, yours is %dx%d.", - minrow + 1 + ROWNO + 3, tty_pi_mincol, + (int) (minrow + 1 + ROWNO + 3), tty_pi_mincol, ttyDisplay->rows, ttyDisplay->cols); tty_wait_synch(); set_option_mod_status("perm_invent", set_gameview); @@ -1739,10 +1728,11 @@ ttyinv_create_window(int newid, struct WinDesc *newwin) newwin->cells[r][c].glyph = 1; } } - + if (!done_tty_perm_invent_init) + tty_invent_box_glyph_init(newwin); return newid; } -#endif +#endif /* TTY_PERM_INVENT */ static void erase_menu_or_text(winid window, struct WinDesc *cw, boolean clear) @@ -2739,7 +2729,7 @@ tty_destroy_nhwindow(winid window) if (cw->type == NHW_MAP) clear_screen(); #ifdef TTY_PERM_INVENT - if (cw->type == NHW_TTYINVENT) { + if (cw->type == NHW_PERMINVENT) { int r, c; if (cw->cells) { @@ -2762,7 +2752,7 @@ tty_destroy_nhwindow(winid window) cw->rows = cw->cols = 0; } cw->maxrow = cw->maxcol = 0; - g.tty_invent_win = WIN_ERR; + g.perm_invent_win = WIN_ERR; } #endif free_window_info(cw, TRUE); @@ -2887,7 +2877,7 @@ tty_putsym(winid window, int x, int y, char ch) case NHW_STATUS: #endif #ifdef TTY_PERM_INVENT - case NHW_TTYINVENT: + case NHW_PERMINVENT: #endif case NHW_MAP: case NHW_BASE: @@ -2959,7 +2949,7 @@ tty_putstr(winid window, int attr, const char *str) return; if (cw->type != NHW_MESSAGE #ifdef TTY_PERM_INVENT - && window != g.tty_invent_win + && window != g.perm_invent_win #endif ) str = compress_str(str); @@ -3457,8 +3447,6 @@ tty_select_menu(winid window, int how, menu_item **menu_list) return n; } -RESTORE_WARNING_FORMAT_NONLITERAL - /* special hack for treating top line --More-- as a one item menu */ char tty_message_menu(char let, int how, const char *mesg) @@ -3491,32 +3479,34 @@ 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_tty_perm_invent_init = FALSE; -static void ttyinv_populate_slot(struct WinDesc *, int, int, const char *); -#ifndef NOINVSYM /* invent.c */ -#define NOINVSYM '#' -#endif -DISABLE_WARNING_FORMAT_NONLITERAL -#endif - /* update persistent inventory window */ void tty_update_inventory(int arg UNUSED) { #ifdef TTY_PERM_INVENT +#ifndef CORE_INVENT static char Empty[1] = { '\0' }; struct WinDesc *cw; struct tty_perminvent_cell *cell; struct obj *obj; char invbuf[BUFSZ], *text, nxtlet; int row, col, side, slot, maxslot; - winid window = g.tty_invent_win; + winid window = g.perm_invent_win; boolean force_redraw = g.program_state.in_docrt ? TRUE : FALSE, show_gold = (ttyinvmode & InvShowGold) != 0, inuse_only = (ttyinvmode & InvInUse) != 0, sparse = (ttyinvmode & InvSparse) != 0; + if (g.perm_invent_win == WIN_ERR + && !done_tty_perm_invent_init && iflags.perm_invent) { + g.perm_invent_win = create_nhwindow(NHW_PERMINVENT); + if (g.perm_invent_win == WIN_ERR) { + tty_perm_invent_toggled(TRUE); /* TRUE means negated */ + return; + } + display_nhwindow(g.perm_invent_win, FALSE); + window = g.perm_invent_win; + } /* we just return if the window creation failed, probably due to not meeting size requirements */ if (window == WIN_ERR) @@ -3624,29 +3614,155 @@ tty_update_inventory(int arg UNUSED) } } calling_from_update_inventory = FALSE; -#endif +#endif /* CORE_INVENT */ +#endif /* TTY_PERM_INVENT */ return; } perminvent_info * tty_update_invent_slot( - winid window UNUSED, /* window to use, must be of type NHW_MENU */ - int inventory_slot UNUSED, /* slot id: 0 - info return to core */ - /* 1 - gold slot */ - /* 2 - 29 obj slots */ - perminvent_info *pi UNUSED) + winid window, /* window to use, must be of type NHW_MENU */ + int slot, + perminvent_info *pi) { +#if !defined(TTY_PERM_INVENT) || !defined(CORE_INVENT) return (perminvent_info *) 0; + nhUse(window); + nhUse(slot); + nhUse(pi); +#else + boolean force_redraw, tty_ok, show_gold, inuse_only; + int row, col, side, maxslot; + /* winid window = g.perm_invent_win; */ + struct WinDesc *cw; + struct tty_perminvent_cell *cell; + /* these types are set match the wintty.h field declarations */ + long minrow; /* long to match maxrow declaration in wintty.h */ + short offx, offy; + long rows, cols, maxrow, maxcol; + + if (!pi) + return (perminvent_info *) 0; + if (!done_tty_perm_invent_init + && pi->fromcore.core_request != request_settings) { + pi->tocore.tocore_flags |= no_init_done; + return pi; + } + + switch(pi->fromcore.core_request) { + case request_settings: { + pi->tocore = zero_tocore; + ttyinvmode = pi->fromcore.invmode; + inuse_only = (ttyinvmode & InvInUse) != 0; + tty_ok = assesstty(pi->fromcore.invmode, + &offx, &offy, &rows, &cols, + &maxcol, &minrow, &maxrow); + pi->tocore.needrows = (int) (minrow + 1 + ROWNO + 3); + pi->tocore.needcols = (int) tty_pi_mincol; + pi->tocore.haverows = (int) ttyDisplay->rows; + pi->tocore.havecols = (int) ttyDisplay->cols; + if (!tty_ok) { + pi->tocore.tocore_flags |= prohibited; /* prohibited */ + return pi; + } + maxslot = (maxrow - 2) * (!inuse_only ? 2 : 1); + pi->tocore.maxslot = maxslot; + return pi; + break; + } + case update_slot: + if ((cw = wins[window]) == (struct WinDesc *) 0) + panic(winpanicstr, window); + slot -= 1; /* 0 is used for commands */ + show_gold = (ttyinvmode & InvShowGold) != 0; + row = (slot % (!show_gold ? 26 : 27)) + 1; /* +1: top border */ + /* side: left side panel or right side panel, not a window column */ + side = slot < (!show_gold ? 26 : 27) ? 0 : 1; + ttyinv_populate_slot(cw, row, side, pi->fromcore.text); + break; + case render: + if ((cw = wins[window]) == (struct WinDesc *) 0) + panic(winpanicstr, window); + /* render to the display */ + force_redraw = pi->fromcore.force_redraw; +// show_gold = (ttyinvmode & InvShowGold) != 0; +// inuse_only = (ttyinvmode & InvInUse) != 0; +// sparse = (ttyinvmode & InvSparse) != 0; +// if (!done_tty_perm_invent_init) + calling_from_update_inventory = TRUE; + 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; + } + } + calling_from_update_inventory = FALSE; + break; + default: + impossible("invalid request to tty_update_invent_slot %u", + pi->fromcore.core_request); + } + return pi; +#endif } +RESTORE_WARNING_FORMAT_NONLITERAL + #ifdef TTY_PERM_INVENT +/* + * returns TRUE if things are ok + */ +static boolean +assesstty( + enum inv_modes invmode, + short *offx, short *offy, long *rows, long *cols, + long *maxcol, long *minrow, long *maxrow) +{ + boolean show_gold, inuse_only; + + show_gold = (invmode & InvShowGold) != 0; + inuse_only = (invmode & InvInUse) != 0; + + *offx = 0; + /* topline + map rows + status lines */ + *offy = 1 + ROWNO + 3; /* 3: + 2 + (iflags.wc2_statuslines > 2) */ + *rows = (ttyDisplay->rows - (*offy)); + *cols = ttyDisplay->cols; + *minrow = tty_pi_minrow; + if (show_gold) + *minrow += 1; + /* "normal" max for items in use would be 3 weapon + 7 armor + 4 + accessories == 14, but being punished and picking up the ball will + add 1, and some quest artifacts have an an #invoke property that's + tracked via obj->owornmask so could add more; if hero ends up with + more than 15 in-use items, some will be left out; + Qt's "paper doll" adds first lit lamp/candle and first active + leash; those aren't tracked via owornmask so we don't notice them */ + if (inuse_only) + *minrow = 1 + 15 + 1; /* top border + 15 lines + bottom border */ + *maxrow = *minrow; + *maxcol = *cols; + return !(*rows < *minrow || *cols < tty_pi_mincol); +} /* put the formatted object description for one item into a particular row and left/right panel, truncating if long or padding with spaces if short */ static void ttyinv_populate_slot( struct WinDesc *cw, - int row, /* 'row' within the window, not within screen */ + int row, /* 'row' within the window, not within screen */ int side, /* 'side'==0 is left panel or ==1 is right panel */ const char *text) { @@ -3680,12 +3796,14 @@ ttyinv_populate_slot( } } +DISABLE_WARNING_FORMAT_NONLITERAL + 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; + winid window = g.perm_invent_win; struct tty_perminvent_cell *cell; if (window == WIN_ERR || !iflags.perm_invent || y < 0) @@ -3718,6 +3836,8 @@ tty_refresh_inventory(int start, int stop, int y) } } +RESTORE_WARNING_FORMAT_NONLITERAL + static void tty_invent_box_glyph_init(struct WinDesc *cw) { @@ -3789,22 +3909,20 @@ tty_invent_box_glyph_init(struct WinDesc *cw) done_tty_perm_invent_init = TRUE; } -RESTORE_WARNING_FORMAT_NONLITERAL - void tty_perm_invent_toggled(boolean negated) { if (negated) { - if (g.tty_invent_win != WIN_ERR) - destroy_nhwindow(g.tty_invent_win), g.tty_invent_win = WIN_ERR; + if (g.perm_invent_win != WIN_ERR) + destroy_nhwindow(g.perm_invent_win), g.perm_invent_win = WIN_ERR; done_tty_perm_invent_init = FALSE; } else { - g.tty_invent_win = create_nhwindow(NHW_TTYINVENT); - if (g.tty_invent_win != WIN_ERR) - display_nhwindow(g.tty_invent_win, FALSE); + g.perm_invent_win = create_nhwindow(NHW_PERMINVENT); + if (g.perm_invent_win != WIN_ERR) + display_nhwindow(g.perm_invent_win, FALSE); } } -#endif +#endif /* TTY_PERM_INVENT */ void tty_mark_synch(void) @@ -3848,8 +3966,8 @@ docorner(register int xmin, register int ymax, int ystart_between_menu_pages) #ifdef TTY_PERM_INVENT struct WinDesc *icw = 0; - if (g.tty_invent_win != WIN_ERR) - icw = wins[g.tty_invent_win]; + if (g.perm_invent_win != WIN_ERR) + icw = wins[g.perm_invent_win]; #endif HUPSKIP(); @@ -3902,7 +4020,8 @@ docorner(register int xmin, register int ymax, int ystart_between_menu_pages) } end_glyphout(); - if (ymax >= (int) wins[WIN_STATUS]->offy) { + if (ymax >= (int) wins[WIN_STATUS]->offy + && !ystart_between_menu_pages) { /* we have wrecked the bottom line */ g.context.botlx = 1; bot();