rework TTY_PERM_INVENT; update window port interface

Change the inner workings of the experimental TTY_PERM_INVENT.

Switch to delivering the content to tty for the experimental perm_invent
via the existing window port interface (start_menu(), add_menu(), end_menu).

This also adds a new window port interface call ctrl_nhwindow() for
delivering information to the window port, and/or obtaining specific
information from the window port. The information and requests can
be extended as required. To be documented later once the changes settle
down.

Due to the intrusive nature of these changes and the possibility of
some bugs in the new code, I'm going to leave TTY_PERM_INVENT commented
out in the repository for a day or two.  Anyone wishing to test it out
can do so by uncommenting TTY_PERM_INVENT in config.h.
This commit is contained in:
nhmall
2022-07-03 00:34:08 -04:00
parent 67e80cc329
commit c84e0ba6e1
28 changed files with 602 additions and 616 deletions

View File

@@ -562,7 +562,7 @@ typedef unsigned char uchar;
/* 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
/* #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

View File

@@ -972,8 +972,10 @@ 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;
winid perm_invent_win;
int core_invent_state;
int in_sync_perminvent;
int perm_invent_toggling_direction;
long glyph_reset_timestamp;
/* query objlist callback: return TRUE if obj type matches "this_type" */
int this_type;

View File

@@ -1176,6 +1176,7 @@ extern const char *currency(long);
extern void silly_thing(const char *, struct obj *);
extern void sync_perminvent(void);
extern void perm_invent_toggled(boolean negated);
extern void prepare_perminvent(winid window);
/* ### ioctl.c ### */

View File

@@ -487,6 +487,6 @@ extern void genl_outrip(winid, int, time_t);
extern void X11_preference_update(const char *);
extern void X11_update_inventory(int);
extern perminvent_info *X11_update_invent_slot(winid, int, perminvent_info *);
extern win_request_info *X11_ctrl_nhwindow(winid, int, win_request_info *);
#endif /* WINX_H */

View File

@@ -113,7 +113,7 @@ extern void genl_outrip(winid tmpwin, int how, time_t when);
extern void curses_preference_update(const char *pref);
extern void curs_reset_windows(boolean, boolean);
extern void curses_update_inventory(int);
extern perminvent_info *curses_update_invent_slot(winid, int, perminvent_info *);
extern win_request_info *curses_ctrl_nhwindow(winid, int, win_request_info *);
/* curswins.c */

View File

@@ -92,7 +92,7 @@ struct window_procs {
unsigned long *);
boolean (*win_can_suspend)(void);
void (*win_update_inventory)(int);
perminvent_info *(*win_update_invent_slot)(winid, int, perminvent_info *);
win_request_info *(*win_ctrl_nhwindow)(winid, int, win_request_info *);
};
extern
@@ -174,7 +174,7 @@ extern
*/
#define status_enablefield (*windowprocs.win_status_enablefield)
#define status_update (*windowprocs.win_status_update)
#define update_invent_slot (*windowprocs.win_update_invent_slot)
#define ctrl_nhwindow (*windowprocs.win_ctrl_nhwindow)
/*
*
@@ -491,7 +491,7 @@ extern void stdio_nonl_raw_print(const char *);
extern void stdio_raw_print_bold(const char *);
extern void stdio_wait_synch(void);
extern void safe_update_inventory(int);
extern perminvent_info *safe_update_invent_slot(winid, int, perminvent_info *);
extern win_request_info *safe_ctrl_nhwindow(winid, int, win_request_info *);
extern int stdio_nhgetch(void);
#endif /* SAFEPROCS */
#endif /* WINPROCS_H */

View File

@@ -12,7 +12,7 @@
#ifdef TTY_PERM_INVENT
enum { tty_pi_minrow = 28, tty_pi_mincol = 79 };
enum { tty_perminv_minrow = 28, tty_perminv_mincol = 79 };
/* for static init of zerottycell, put pointer first */
union ttycellcontent {
glyph_info *gi;
@@ -283,7 +283,7 @@ E void genl_outrip(winid, int, time_t);
E char *tty_getmsghistory(boolean);
E void tty_putmsghistory(const char *, boolean);
E void tty_update_inventory(int);
E perminvent_info *tty_update_invent_slot(winid, int, perminvent_info *);
E win_request_info *tty_ctrl_nhwindow(winid, int, win_request_info *);
#ifdef TTY_PERM_INVENT
E void tty_refresh_inventory(int start, int stop, int y);

View File

@@ -169,6 +169,9 @@ typedef struct gi {
*/
#define MENU_BEHAVE_STANDARD 0x0000000U
#define MENU_BEHAVE_PERMINV 0x0000001U
enum perm_invent_toggles {toggling_off = -1, toggling_not = 0, toggling_on = 1 };
/* inventory modes */
enum inv_modes { InvNormal = 0, InvShowGold = 1, InvSparse = 2, InvInUse = 4 };
@@ -180,9 +183,8 @@ enum to_core_flags {
};
enum from_core_requests {
request_settings = 1,
update_slot = 2,
render = 3
set_mode = 1,
request_settings = 2,
};
struct to_core {
@@ -197,24 +199,16 @@ struct to_core {
struct from_core {
enum from_core_requests core_request;
enum inv_modes invmode;
boolean force_redraw;
int slot; /* which inventory slot + 1; 0 indicates request */
int invlet;
char text[BUFSZ];
int32_t clr; /* adjusted color 0 = ignore
* 1-16 = NetHack color + 1
* 17..16,777,233 = 24-bit color + 17
*/
};
struct perminvent_info_t {
struct win_request_info_t {
struct to_core tocore;
struct from_core fromcore;
};
typedef struct perminvent_info_t perminvent_info;
typedef struct win_request_info_t win_request_info;
#define CORE_INVENT
/* #define CORE_INVENT */
/* clang-format on */

View File

@@ -619,6 +619,8 @@ stop_occupation(void)
void
display_gamewindows(void)
{
int menu_behavior = MENU_BEHAVE_STANDARD;
WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
if (VIA_WINDOWPORT()) {
status_initialize(0);
@@ -627,9 +629,15 @@ display_gamewindows(void)
}
WIN_MAP = create_nhwindow(NHW_MAP);
WIN_INVEN = create_nhwindow(NHW_MENU);
#ifdef TTY_PERM_INVENT
if (WINDOWPORT(tty) && WIN_INVEN != WIN_ERR) {
menu_behavior = MENU_BEHAVE_PERMINV;
prepare_perminvent(WIN_INVEN);
}
#endif
/* in case of early quit where WIN_INVEN could be destroyed before
ever having been used, use it here to pacify the Qt interface */
start_menu(WIN_INVEN, 0U), end_menu(WIN_INVEN, (char *) 0);
start_menu(WIN_INVEN, menu_behavior), end_menu(WIN_INVEN, (char *) 0);
#ifdef MAC
/* This _is_ the right place for this - maybe we will

View File

@@ -435,8 +435,10 @@ const struct instance_globals g_init = {
NULL, /* invbuf */
0, /* inbufsize */
WIN_ERR, /* cached_pickinv_win */
WIN_ERR, /* perm_invent_win */
0, /* core_invent_state */
0, /* in_sync_perminvent */
0, /* perm_invent_toggling_direction */
0L, /* glyph_reset_timestamp */
0, /* this_type */
NULL, /* this_title */
UNDEFINED_VALUES, /* only (coord) */

View File

@@ -2775,6 +2775,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
color = NO_COLOR;
gmap->sym.color = color;
}
g.glyph_reset_timestamp = g.moves;
}
/* ------------------------------------------------------------------------ */

View File

@@ -42,6 +42,12 @@ static boolean item_naming_classification(struct obj *, char *, char *);
static int item_reading_classification(struct obj *, char *);
static void mime_action(const char *);
/* enum and structs are defined in wintype.h */
static win_request_info zerowri = { { 0L, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 } };
static win_request_info wri_info;
static int done_setting_perminv_flags = 0;
static boolean in_perm_invent_toggled;
/* wizards can wish for venom, which will become an invisible inventory
* item without this. putting it in inv_order would mean venom would
* suddenly become a choice for all the inventory-class commands, which
@@ -2440,7 +2446,7 @@ update_inventory(void)
*/
save_suppress_price = iflags.suppress_price;
iflags.suppress_price = 0;
#if defined(TTY_PERM_INVENT) && defined(CORE_INVENT)
#if defined(TTY_PERM_INVENT)
if (WINDOWPORT(tty))
sync_perminvent();
else
@@ -3183,27 +3189,40 @@ display_pickinv(
char ilet, ret, *formattedobj;
const char *invlet = flags.inv_order;
int n, classcount;
winid win; /* windows being used */
winid win; /* windows being used */
anything any;
menu_item *selected;
unsigned sortflags;
Loot *sortedinvent, *srtinv;
boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE;
int clr = 0;
int clr = 0, menu_behavior = MENU_BEHAVE_STANDARD;
boolean show_gold = TRUE, sparse = FALSE, inuse_only = FALSE,
doing_perm_invent = FALSE, save_flags_sortpack = flags.sortpack;
if (lets && !*lets)
lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
if (iflags.perm_invent && (lets || xtra_choice || wizid)) {
if ((iflags.perm_invent && (lets || xtra_choice || wizid))
#ifdef TTY_PERM_INVENT
|| !g.in_sync_perminvent
#endif
|| WIN_INVEN == WIN_ERR) {
/* partial inventory in perm_invent setting; don't operate on
full inventory window, use an alternate one instead; create
the first time needed and keep it for re-use as needed later */
if (g.cached_pickinv_win == WIN_ERR)
g.cached_pickinv_win = create_nhwindow(NHW_MENU);
win = g.cached_pickinv_win;
} else
} else {
win = WIN_INVEN;
menu_behavior = MENU_BEHAVE_PERMINV;
prepare_perminvent(win);
show_gold = ((wri_info.fromcore.invmode & InvShowGold) != 0);
sparse = ((wri_info.fromcore.invmode & InvSparse) != 0);
inuse_only = ((wri_info.fromcore.invmode & InvInUse) != 0);
doing_perm_invent = TRUE;
nhUse(sparse);
}
/*
* Exit early if no inventory -- but keep going if we are doing
* a permanent inventory update. We need to keep going so the
@@ -3266,10 +3285,18 @@ display_pickinv(
sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
if (flags.sortpack)
sortflags |= SORTLOOT_PACK;
#ifdef TTY_PERM_INVENT
if (doing_perm_invent && WINDOWPORT(tty)) {
sortflags = SORTLOOT_INVLET;
save_flags_sortpack = flags.sortpack;
flags.sortpack = FALSE;
}
#else
nhUse(save_flags_sortpack);
#endif
sortedinvent = sortloot(&g.invent, sortflags, FALSE,
(boolean (*)(OBJ_P)) 0);
start_menu(win, MENU_BEHAVE_STANDARD);
start_menu(win, menu_behavior);
any = cg.zeroany;
if (wizid) {
int unid_cnt;
@@ -3327,6 +3354,11 @@ display_pickinv(
if (!flags.sortpack || otmp->oclass == *invlet) {
if (wizid && !not_fully_identified(otmp))
continue;
if (doing_perm_invent
&& ((otmp->invlet == GOLD_SYM && !show_gold)
|| ((otmp->invlet != GOLD_SYM)
&& (!otmp->owornmask && inuse_only))))
continue;
any = cg.zeroany; /* all bits zero */
ilet = otmp->invlet;
if (flags.sortpack && !classcount) {
@@ -3387,6 +3419,10 @@ display_pickinv(
not_carrying_anything, MENU_ITEMFLAGS_NONE);
want_reply = FALSE;
}
#ifdef TTY_PERM_INVENT
if (doing_perm_invent && WINDOWPORT(tty))
flags.sortpack = save_flags_sortpack;
#endif
end_menu(win, (query && *query) ? query : (char *) 0);
n = select_menu(win,
@@ -5361,47 +5397,39 @@ display_binventory(coordxy x, coordxy y, boolean as_if_seen)
return n;
}
#if defined(CORE_INVENT)
/* enum and structs are defined in wintype.h */
static perminvent_info zeropi = { {0L,0,0,0,0,0,0,0}, {0,0,0,0,0,{0},0} };
static perminvent_info pi_info;
static char Empty[1] = { '\0' };
static int done_environment_var = 0;
#ifdef TTY_PERM_INVENT
extern void tty_perm_invent_toggled(boolean negated);
static boolean in_perm_invent_toggled;
#endif
void
prepare_perminvent(winid window)
{
win_request_info *wri UNUSED;
if (!done_setting_perminv_flags) {
wri_info = zerowri;
/*TEMPORARY*/
char *envtmp = nh_getenv("TTYINV");
wri_info.fromcore.invmode = envtmp ? atoi(envtmp) : InvNormal;
/* relay the mode settings to the window port */
wri = ctrl_nhwindow(window, set_mode, &wri_info);
done_setting_perminv_flags = 1;
}
}
void
sync_perminvent(void)
{
static perminvent_info *pi = 0;
char *text, nxtlet;
int slot;
boolean show_gold, inuse_only, sparse;
static win_request_info *wri = 0;
const char *wport_id;
struct obj *obj;
if (!done_environment_var) {
pi_info = zeropi;
/*TEMPORARY*/
char *envtmp = nh_getenv("TTYINV");
pi_info.fromcore.invmode = envtmp ? atoi(envtmp) : InvNormal;
done_environment_var = 1;
}
show_gold = (pi_info.fromcore.invmode & InvShowGold) != 0;
inuse_only = (pi_info.fromcore.invmode & InvInUse) != 0;
sparse = (pi_info.fromcore.invmode & InvSparse) != 0;
if ((g.perm_invent_win == WIN_ERR && g.core_invent_state)
|| (pi_info.tocore.tocore_flags & prohibited))
if (WIN_INVEN == WIN_ERR) {
if ((g.core_invent_state
|| (wri_info.tocore.tocore_flags & prohibited))
&& !(in_perm_invent_toggled
&& g.perm_invent_toggling_direction == toggling_on))
return;
}
if (!done_setting_perminv_flags && WIN_INVEN != WIN_ERR)
prepare_perminvent(WIN_INVEN);
if ((!iflags.perm_invent && g.core_invent_state)
#ifdef TTY_PERM_INVENT
&& !in_perm_invent_toggled
#endif
){
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.
@@ -5413,157 +5441,81 @@ sync_perminvent(void)
(void) doredraw();
return;
}
if (!iflags.perm_invent
#ifdef TTY_PERM_INVENT
&& !in_perm_invent_toggled
#endif
)
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 following conditions can bring us to here:
* 1. iflags.perm_invent is on
* AND
* g.core_invent_state is still zero.
*
* The window port informs the core of the number of
* slots that it will process.
* OR
*
* 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.
* 2. iflags.perm_invent is off, but we're in the
* midst of toggling it on.
*/
if (WINDOWPORT(tty) && iflags.perm_invent)
wport_id = "tty perm_invent";
else
wport_id = "perm_invent";
pi_info.fromcore.core_request = 0;
if ((iflags.perm_invent && !g.core_invent_state)
#ifdef TTY_PERM_INVENT
|| in_perm_invent_toggled
#endif
) {
/* 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;
|| ((!iflags.perm_invent
&& (in_perm_invent_toggled
&& g.perm_invent_toggling_direction == toggling_on)))) {
/* Send windowport a request to return the related settings to us */
if ((iflags.perm_invent && !g.core_invent_state)
|| in_perm_invent_toggled) {
if ((wri = ctrl_nhwindow(WIN_INVEN, request_settings, &wri_info))) {
if ((wri->tocore.tocore_flags & prohibited) != 0) {
/* sizes aren't good enough */
set_option_mod_status("perm_invent", set_gameview);
iflags.perm_invent = FALSE;
if (WIN_INVEN != WIN_ERR)
destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR;
if (WINDOWPORT(tty) && iflags.perm_invent)
wport_id = "tty perm_invent";
else
wport_id = "perm_invent";
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, wri->tocore.needrows,
wri->tocore.needcols, wri->tocore.haverows,
wri->tocore.havecols);
wait_synch();
return;
}
}
g.core_invent_state++;
}
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++;
}
if (!pi || pi->tocore.maxslot == 0)
if (!wri || wri->tocore.maxslot == 0)
return;
text = Empty; /* lint suppression */
pi_info.fromcore.core_request = update_slot;
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);
if (in_perm_invent_toggled && g.perm_invent_toggling_direction == toggling_on) {
WIN_INVEN = create_nhwindow(NHW_MENU);
}
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);
pi_info.fromcore.core_request = 0;
if (WIN_INVEN != WIN_ERR && g.program_state.beyond_savefile_load) {
g.in_sync_perminvent = 1;
(void) display_inventory((char *) 0, FALSE);
g.in_sync_perminvent = 0;
}
}
void
perm_invent_toggled(boolean negated)
{
#ifdef TTY_PERM_INVENT
in_perm_invent_toggled = TRUE;
#endif
if (negated) {
if (g.perm_invent_win != WIN_ERR)
destroy_nhwindow(g.perm_invent_win), g.perm_invent_win = WIN_ERR;
g.perm_invent_toggling_direction = toggling_off;
if (WIN_INVEN != WIN_ERR)
destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR;
g.core_invent_state = 0;
} else {
g.perm_invent_toggling_direction = toggling_on;
sync_perminvent();
}
#ifdef TTY_PERM_INVENT
g.perm_invent_toggling_direction = toggling_not;
in_perm_invent_toggled = FALSE;
#endif
}
#endif /* CORE_INVENT */
/*invent.c*/

View File

@@ -96,13 +96,13 @@ char optbuf[COLBUFSZ];
static struct version_info version;
static const char opt_indent[] = " ";
struct win_info {
struct win_information {
const char *id, /* DEFAULT_WINDOW_SYS string */
*name; /* description, often same as id */
boolean valid;
};
static struct win_info window_opts[] = {
static struct win_information window_opts[] = {
#ifdef TTY_GRAPHICS
{ "tty",
/* testing 'USE_TILES' here would bring confusion because it could

View File

@@ -4415,7 +4415,7 @@ optfn_boolean(int optidx, int req, boolean negated, char *opts, char *op)
-> sync_perminvent()
-> tty_create_nhwindow(NHW_PERMINVENT)
gives feedback for failure (terminal too small) */
if (g.perm_invent_win == WIN_ERR)
if (WIN_INVEN == WIN_ERR)
return optn_silenterr;
}
#endif
@@ -8964,6 +8964,10 @@ enhance_menu_text(
if (thisopt->setwhere == set_gameview)
Snprintf(eos(buf), availsz, " *terminal size is too small");
}
#else
nhUse(availsz);
nhUse(bool_p);
nhUse(thisopt);
#endif
return;
}

View File

@@ -536,7 +536,7 @@ static void hup_void_fdecl_int(int);
static void hup_void_fdecl_winid(winid);
static void hup_void_fdecl_winid_ulong(winid, unsigned long);
static void hup_void_fdecl_constchar_p(const char *);
static perminvent_info *hup_update_invent_slot(winid, int, perminvent_info *);
static win_request_info *hup_ctrl_nhwindow(winid, int, win_request_info *);
static struct window_procs hup_procs = {
WPID(hup), 0L, 0L,
@@ -585,7 +585,7 @@ static struct window_procs hup_procs = {
genl_status_enablefield, hup_status_update,
genl_can_suspend_no,
hup_void_fdecl_int, /* update_inventory */
hup_update_invent_slot, /* update_invent_slot */
hup_ctrl_nhwindow,
};
static void (*previnterface_exit_nhwindows)(const char *) = 0;
@@ -841,15 +841,13 @@ hup_void_fdecl_constchar_p(const char *string UNUSED)
}
/*ARGUSED*/
perminvent_info *
hup_update_invent_slot(
win_request_info *
hup_ctrl_nhwindow(
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)
int request UNUSED,
win_request_info *wri UNUSED)
{
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
#endif /* HANGUPHANDLING */

View File

@@ -35,6 +35,12 @@
#pragma pack(8)
#endif
#ifdef DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

View File

@@ -5,6 +5,7 @@
/* main.c - Windows */
#include "win32api.h" /* for GetModuleFileName */
#include "hack.h"
#ifdef DLB
#include "dlb.h"
@@ -424,6 +425,10 @@ mingw_main(int argc, char *argv[])
char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
char failbuf[BUFSZ];
#ifdef _MSC_VER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
/*
* Get a set of valid safe windowport function
* pointers during early startup initialization.

View File

@@ -490,15 +490,13 @@ void NetHackQtBind::qt_update_inventory(int arg UNUSED)
*/
}
perminvent_info *NetHackQtBind::qt_update_invent_slot(
winid wid 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)
win_request_info *NetHackQtBind::qt_ctrl_nhwindow(
winid wid UNUSED,
int request UNUSED,
win_request_info *wri UNUSED)
{
NetHackQtWindow* window UNUSED =id_to_window[(int)wid];
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
void NetHackQtBind::qt_mark_synch()
@@ -1111,7 +1109,7 @@ struct window_procs Qt_procs = {
#endif
genl_can_suspend_yes,
nethack_qt_::NetHackQtBind::qt_update_inventory,
nethack_qt_::NetHackQtBind::qt_update_invent_slot,
nethack_qt_::NetHackQtBind::qt_ctrl_nhwindow,
};
#ifndef WIN32

View File

@@ -89,7 +89,7 @@ public:
static void qt_outrip(winid wid, int how, time_t when);
static int qt_kbhit();
static void qt_update_inventory(int);
static perminvent_info *qt_update_invent_slot(winid, int, perminvent_info *);
static win_request_info *qt_ctrl_nhwindow(winid, int, win_request_info *);
static QWidget *mainWidget() { return main; }

View File

@@ -142,7 +142,7 @@ struct window_procs X11_procs = {
X11_status_update,
genl_can_suspend_no, /* XXX may not always be correct */
X11_update_inventory,
X11_update_invent_slot,
X11_ctrl_nhwindow,
};
/*
@@ -1272,15 +1272,13 @@ X11_update_inventory(int arg)
return;
}
perminvent_info *
X11_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)
win_request_info *
X11_ctrl_nhwindow(
winid window UNUSED,
int request UNUSED,
win_request_info *wri UNUSED)
{
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
/* The current implementation has all of the saved lines on the screen. */

View File

@@ -75,7 +75,7 @@ void chainin_status_update(int, genericptr_t, int, int, int,
boolean chainin_can_suspend(void);
void chainin_update_inventory(int);
perminvent_info *chainin_update_invent_slot(winid, int, perminvent_info *);
win_request_info *chainin_ctrl_nhwindow(winid, int, win_request_info *);
void *chainin_procs_chain(int cmd, int n, void *me, void *nextprocs, void *nextdata);
void chainin_procs_init(int dir);
@@ -578,18 +578,16 @@ chainin_can_suspend(void)
return rv;
}
perminvent_info *
chainin_update_invent_slot(
winid window, /* window to use, must be of type NHW_MENU */
int inventory_slot, /* slot id: 0 - info return to core */
/* 1 - gold slot */
/* 2 - 29 obj slots */
perminvent_info *pi)
win_request_info *
chainin_ctrl_nhwindow(
winid window,
int request,
win_request_info *wri)
{
boolean rv;
rv = (*cibase->nprocs->win_update_invent_slot)(cibase->ndata, window,
inventory_slot, pi);
rv = (*cibase->nprocs->win_ctrl_nhwindow)(cibase->ndata, window,
request, wri);
return rv;
}
@@ -639,5 +637,5 @@ struct window_procs chainin_procs = {
chainin_status_update,
chainin_can_suspend,
chainin_update_inventory,
chainin_update_invent_slot,
chainin_ctrl_nhwindow,
};

View File

@@ -75,7 +75,7 @@ void chainout_status_update(void *,int, genericptr_t, int, int, int,
boolean chainout_can_suspend(void *);
void chainout_update_inventory(void *, int);
perminvent_info *chainout_update_invent_slot(void *, winid, int, perminvent_info *);
win_request_info *chainout_ctrl_nhwindow(void *, winid, int, win_request_info *);
void chainout_procs_init(int dir);
void *chainout_procs_chain(int cmd, int n, void *me, void *nextprocs, void *nextdata);
@@ -700,19 +700,17 @@ chainout_can_suspend(void *vp)
return rv;
}
perminvent_info *
chainout_update_invent_slot(
winid window, /* window to use, must be of type NHW_MENU */
int inventory_slot, /* slot id: 0 - info return to core */
/* 1 - gold slot */
/* 2 - 29 obj slots */
perminvent_info *pi)
win_request_info *
chainout_ctrl_nhwindow(
winid window,
int request,
win_request_info *wri)
{
struct chainout_data *tdp = vp;
boolean rv;
rv = (*tdp->nprocs->win_update_invent_slot)(window,
inventory_slot, pi);
rv = (*tdp->nprocs->win_ctrl_nhwindow)(window,
request, wri);
return rv;
}
@@ -763,5 +761,5 @@ struct chain_procs chainout_procs = {
chainout_status_update,
chainout_can_suspend,
chainout_update_inventory,
chainout_update_invent_slot,
chainout_ctrl_nhwindow,
};

View File

@@ -117,7 +117,7 @@ struct window_procs curses_procs = {
curses_status_update,
genl_can_suspend_yes,
curses_update_inventory,
curses_update_invent_slot,
curses_ctrl_nhwindow,
};
/*
@@ -695,15 +695,13 @@ curses_update_inventory(int arg)
}
}
perminvent_info *
curses_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)
win_request_info *
curses_ctrl_nhwindow(
winid window UNUSED,
int request UNUSED,
win_request_info *wri UNUSED)
{
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
/*

View File

@@ -101,7 +101,7 @@ struct window_procs safe_procs = {
safe_status_update,
safe_can_suspend,
safe_update_inventory,
safe_update_invent_slot,
safe_ctrl_nhwindow,
};
struct window_procs *
@@ -479,15 +479,13 @@ safe_update_inventory(int arg UNUSED)
return;
}
perminvent_info *
safe_update_invent_slot(
winid window, /* window to use, must be of type NHW_MENU */
int inventory_slot, /* slot id: 0 - info return to core */
/* 1 - gold slot */
/* 2 - 29 obj slots */
perminvent_info *pi)
win_request_info *
safe_ctrl_nhwindow(
winid window,
int request,
win_request_info *wri)
{
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
/**************************************************************

View File

@@ -183,21 +183,19 @@ void shim_update_inventory(int a1 UNUSED) {
display_inventory(NULL, FALSE);
}
}
perminvent_info *
shim_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) {
return (perminvent_info *) 0;
win_request_info *
shim_ctrl_nhwindow(
winid window UNUSED,
int request,
win_request_info *wri UNUSED) {
return (win_request_info *) 0;
}
#else /* !__EMSCRIPTEN__ */
VDECLCB(shim_update_inventory,(int a1 UNUSED)
DECLB(perminvent_info *, shim_update_invent_slot,
(winid window, int inventory_slot, perminvent_info *pi),
DECLB(win_request_info *, shim_ctrl_nhwindow,
(winid window, int request, win_request_info *wri),
"viip",
A2P window UNUSED, A2P inventory_slot UNUSED, P2V pi UNUSED)
A2P window UNUSED, A2P request UNUSED, P2V wri UNUSED)
#endif
/* Interface definition used in windows.c */
@@ -257,7 +255,7 @@ struct window_procs shim_procs = {
#endif
genl_can_suspend_yes,
shim_update_inventory,
shim_update_invent_slot,
shim_ctrl_nhwindow,
};
#ifdef __EMSCRIPTEN__

View File

@@ -167,7 +167,7 @@ struct window_procs tty_procs = {
#endif
genl_can_suspend_yes,
tty_update_inventory,
tty_update_invent_slot,
tty_ctrl_nhwindow,
};
winid BASE_WINDOW;
@@ -254,28 +254,32 @@ void g_pututf8(uint8 *utf8str);
#endif
#ifdef TTY_PERM_INVENT
void tty_perm_invent_toggled(boolean negated);
static char Empty[1] = { '\0' };
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 */
static int ttyinvmode = InvNormal; /* enum is in wintype.h */
static int inuse_only_start = 0;
static boolean done_tty_perm_invent_init = FALSE;
enum { tty_slots = 52 + 1 + 1 };
static boolean slot_tracker[tty_slots];
static long last_glyph_reset_when;
#ifndef NOINVSYM /* invent.c */
#define NOINVSYM '#'
#endif
/* not static, core_update_invent_slot() needs to see it from invent.c */
boolean in_tty_perm_invent_toggled = FALSE;
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 int ttyinv_create_window(int, struct WinDesc *);
static void ttyinv_add_menu(winid, struct WinDesc *, char ch, int attr,
int clr, const char *str);
static void ttyinv_render(winid window, struct WinDesc *cw);
static void tty_invent_box_glyph_init(struct WinDesc *cw);
static boolean assesstty(enum inv_modes, short *, short *,
long *, long *, long *, long *, long *);
static void ttyinv_populate_slot(struct WinDesc *, int, int, const char *, int32_t);
long *, long *, long *, long *, long *);
static void ttyinv_populate_slot(struct WinDesc *, int, int,
const char *, int32_t);
static int selector_to_slot(char ch, const int invflags, boolean *ignore);
#endif
/*
@@ -564,8 +568,8 @@ tty_preference_update(const char *pref)
the way to render them might change too (Handling: DEC/UTF8/&c) */
if ((!strcmp(pref, "symset") || !strcmp(pref, "perm_invent"))
&& iflags.window_inited) {
if (g.perm_invent_win != WIN_ERR)
tty_invent_box_glyph_init(wins[g.perm_invent_win]);
if (WIN_INVEN != WIN_ERR)
tty_invent_box_glyph_init(wins[WIN_INVEN]);
}
#endif
return;
@@ -1617,10 +1621,6 @@ tty_create_nhwindow(int type)
newwin->cols = ttyDisplay->cols;
newwin->maxrow = newwin->maxcol = 0;
break;
#ifdef TTY_PERM_INVENT
case NHW_PERMINVENT:
return ttyinv_create_window(newid, newwin);
#endif
default:
panic("Tried to create window type %d\n", (int) type);
/*NOTREACHED*/
@@ -1651,100 +1651,6 @@ tty_create_nhwindow(int type)
return newid;
}
#ifdef TTY_PERM_INVENT
static int
ttyinv_create_window(int newid, struct WinDesc *newwin)
{
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?
* Rows:
* Top border line (1)
* 26 inventory rows (26)
* [should be 27 to have room for '$' and '#']
* 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).
* [The top and bottom borderlines aren't necessary. Suppressing
* them would reduce the number of rows needed by 2.]
*
*/
/* preliminary init in case tty_desctroy_nhwindow() gets called */
newwin->data = (char **) 0;
newwin->datlen = (short *) 0;
newwin->cells = (struct tty_perminvent_cell **) 0;
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.",
(int) (minrow + 1 + ROWNO + 3), tty_pi_mincol,
ttyDisplay->rows, ttyDisplay->cols);
tty_wait_synch();
set_option_mod_status("perm_invent", set_gameview);
iflags.perm_invent = FALSE;
return WIN_ERR;
}
/*
* Terminal/window/screen is big enough.
*/
newwin->maxrow = minrow;
newwin->maxcol = newwin->cols;
/* establish the borders */
bordercol[border_left] = 0;
bordercol[border_middle] = (newwin->maxcol + 1) / 2;
bordercol[border_right] = newwin->maxcol - 1;
/* for in-use mode, use full lines */
if ((ttyinvmode & InvInUse) != 0)
bordercol[border_middle] = bordercol[border_right];
n = (unsigned) (newwin->maxrow * sizeof (struct tty_perminvent_cell *));
newwin->cells = (struct tty_perminvent_cell **) alloc(n);
n = (unsigned) (newwin->maxcol * sizeof (struct tty_perminvent_cell));
for (i = 0; i < newwin->maxrow; i++)
newwin->cells[i] = (struct tty_perminvent_cell *) alloc(n);
n = (unsigned) sizeof (glyph_info);
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;
}
}
if (!done_tty_perm_invent_init)
tty_invent_box_glyph_init(newwin);
return newid;
}
#endif /* TTY_PERM_INVENT */
static void
erase_menu_or_text(winid window, struct WinDesc *cw, boolean clear)
{
@@ -2764,7 +2670,7 @@ tty_destroy_nhwindow(winid window)
cw->rows = cw->cols = 0;
}
cw->maxrow = cw->maxcol = 0;
g.perm_invent_win = WIN_ERR;
WIN_INVEN = WIN_ERR;
done_tty_perm_invent_init = FALSE;
}
#endif
@@ -2961,7 +2867,7 @@ tty_putstr(winid window, int attr, const char *str)
return;
if (cw->type != NHW_MESSAGE
#ifdef TTY_PERM_INVENT
&& window != g.perm_invent_win
&& window != WIN_INVEN
#endif
)
str = compress_str(str);
@@ -3221,12 +3127,37 @@ tty_display_file(const char *fname, boolean complain)
void
tty_start_menu(winid window, unsigned long mbehavior)
{
wins[window]->mbehavior = mbehavior;
struct WinDesc *cw = 0;
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
panic(winpanicstr, window);
#ifdef TTY_PERM_INVENT
if (window != WIN_ERR && cw->mbehavior == MENU_BEHAVE_PERMINV) {
/* PERMINV is ready to go already; not much to do here */
inuse_only_start = 0;
return;
}
if (mbehavior == MENU_BEHAVE_PERMINV
&& (iflags.perm_invent
|| g.perm_invent_toggling_direction == toggling_on)) {
winid w = ttyinv_create_window(window, wins[window]);
if (w == WIN_ERR) {
/* something went wrong, so add clean up code here */
} else {
cw->mbehavior = mbehavior;
}
return;
}
#else
nhUse(mbehavior);
#endif
tty_clear_nhwindow(window);
return;
}
/*ARGSUSED*/
/*ARGSUSED*/
/*
* Add a menu item to the beginning of the menu list. This list is reversed
* later.
@@ -3259,6 +3190,13 @@ tty_add_menu(
|| cw->type != NHW_MENU)
panic(winpanicstr, window);
#ifdef TTY_PERM_INVENT
if (cw->mbehavior == MENU_BEHAVE_PERMINV) {
ttyinv_add_menu(window, cw, ch, attr, clr, str);
return;
}
#endif
cw->nitems++;
if (identifier->a_void) {
int len = (int) strlen(str);
@@ -3322,8 +3260,23 @@ tty_end_menu(winid window, /* menu to use */
int clr = 0;
if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0
|| cw->type != NHW_MENU)
|| cw->type != NHW_MENU) {
/* this can happen if start_menu failed due to size requirements
for the tty perm inventory window. It isn't a situation that
requires a panic, just an early return. */
if (window == WIN_INVEN && !cw)
return;
panic(winpanicstr, window);
}
#ifdef TTY_PERM_INVENT
if (cw->mbehavior == MENU_BEHAVE_PERMINV
&& (iflags.perm_invent || g.perm_invent_toggling_direction == toggling_on)
&& window == WIN_INVEN) {
if (g.program_state.in_moveloop)
ttyinv_render(window, cw);
return;
}
#endif
/* Reverse the list so that items are in correct order. */
cw->mlist = reverse(cw->mlist);
@@ -3433,6 +3386,9 @@ tty_select_menu(winid window, int how, menu_item **menu_list)
|| cw->type != NHW_MENU)
panic(winpanicstr, window);
if (cw->mbehavior == MENU_BEHAVE_PERMINV) {
return 0;
}
*menu_list = (menu_item *) 0;
cw->how = (short) how;
morc = 0;
@@ -3493,129 +3449,287 @@ tty_message_menu(char let, int how, const char *mesg)
return ((how == PICK_ONE && morc == let) || morc == '\033') ? morc : '\0';
}
/* update persistent inventory window */
void
tty_update_inventory(int arg UNUSED)
RESTORE_WARNING_FORMAT_NONLITERAL
win_request_info *
tty_ctrl_nhwindow(winid window UNUSED, int request, win_request_info *wri)
{
#if !defined(TTY_PERM_INVENT)
return (win_request_info *) 0;
nhUse(window);
nhUse(request);
nhUse(wri);
#else
boolean tty_ok /*, show_gold */, inuse_only;
int maxslot;
/* 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 (!wri)
return (win_request_info *) 0;
switch (request) {
case set_mode:
case request_settings:
ttyinvmode = wri->fromcore.invmode;
/* show_gold = (ttyinvmode & InvShowGold) != 0; */
inuse_only = ((ttyinvmode & InvInUse) != 0);
if (request == set_mode)
break;
wri->tocore = zero_tocore;
tty_ok = assesstty(ttyinvmode, &offx, &offy, &rows, &cols, &maxcol,
&minrow, &maxrow);
wri->tocore.needrows = (int) (minrow + 1 + ROWNO + 3);
wri->tocore.needcols = (int) tty_perminv_mincol;
wri->tocore.haverows = (int) ttyDisplay->rows;
wri->tocore.havecols = (int) ttyDisplay->cols;
if (!tty_ok) {
wri->tocore.tocore_flags |= prohibited; /* prohibited */
return wri;
}
maxslot = (maxrow - 2) * (!inuse_only ? 2 : 1);
wri->tocore.maxslot = maxslot;
return wri;
break;
default:
impossible("invalid request to tty_update_invent_slot %u", request);
}
return wri;
#endif
}
#ifdef TTY_PERM_INVENT
#ifndef CORE_INVENT
static char Empty[1] = { '\0' };
struct WinDesc *cw;
static int
ttyinv_create_window(int newid, struct WinDesc *newwin)
{
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?
* Rows:
* Top border line (1)
* 26 inventory rows (26)
* [should be 27 to have room for '$' and '#']
* 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).
* [The top and bottom borderlines aren't necessary. Suppressing
* them would reduce the number of rows needed by 2.]
*
*/
/* preliminary init in case tty_desctroy_nhwindow() gets called */
newwin->data = (char **) 0;
newwin->datlen = (short *) 0;
newwin->cells = (struct tty_perminvent_cell **) 0;
if (!assesstty(ttyinvmode, &newwin->offx, &newwin->offy, &newwin->rows,
&newwin->cols, &newwin->maxcol, &minrow,
&newwin->maxrow)) {
tty_destroy_nhwindow(newid); /* sets WIN_INVEN 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.",
(int) (minrow + 1 + ROWNO + 3), tty_perminv_mincol,
ttyDisplay->rows, ttyDisplay->cols);
tty_wait_synch();
set_option_mod_status("perm_invent", set_gameview);
iflags.perm_invent = FALSE;
return WIN_ERR;
}
/*
* Terminal/window/screen is big enough.
*/
newwin->maxrow = minrow;
newwin->maxcol = newwin->cols;
/* establish the borders */
bordercol[border_left] = 0;
bordercol[border_middle] = (newwin->maxcol + 1) / 2;
bordercol[border_right] = newwin->maxcol - 1;
/* for in-use mode, use full lines */
if ((ttyinvmode & InvInUse) != 0)
bordercol[border_middle] = bordercol[border_right];
n = (unsigned) (newwin->maxrow * sizeof(struct tty_perminvent_cell *));
newwin->cells = (struct tty_perminvent_cell **) alloc(n);
n = (unsigned) (newwin->maxcol * sizeof(struct tty_perminvent_cell));
for (i = 0; i < newwin->maxrow; i++)
newwin->cells[i] = (struct tty_perminvent_cell *) alloc(n);
n = (unsigned) sizeof(glyph_info);
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;
tty_invent_box_glyph_init(newwin);
return newid;
}
static void
ttyinv_add_menu(winid window UNUSED, struct WinDesc *cw, char ch,
int attr UNUSED, int clr UNUSED, const char *str)
{
char invbuf[BUFSZ];
const char *text;
boolean inuse_only = (ttyinvmode & InvInUse) != 0,
show_gold = (ttyinvmode & InvShowGold) != 0,
/* sparse = (ttyinvmode & InvSparse) != 0, */
ignore = FALSE;
int row, side, slot = 0, rows_per_side = (!show_gold ? 26 : 27);
if (!g.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); */
/* TODO: check for MENUCOLORS match */
text = str; /* 'text' will switch to invbuf[] 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(invbuf, sizeof invbuf, "%c - %s", ch, text);
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);
}
return;
}
static int
selector_to_slot(char ch, const int invflags, boolean *ignore)
{
int slot = 0;
boolean show_gold = (invflags & InvShowGold) != 0,
inuse_only = (invflags & InvInUse) != 0;
#if 0
sparse = (invflags & InvSparse) != 0,
#endif
*ignore = FALSE;
switch (ch) {
case '$':
if (!show_gold)
*ignore = TRUE;
slot = 0;
break;
case '#':
slot = 52 + (show_gold ? 1 : 0);
break;
case 0:
*ignore = TRUE;
break;
default:
if (!inuse_only) {
if (ch >= 'a' && ch <= 'z')
slot = (ch - 'a') + (show_gold ? 1 : 0);
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++;
}
}
return slot;
}
static void
ttyinv_render(winid window, struct WinDesc *cw)
{
int row, col, slot, side, filled_count = 0, slot_limit;
struct tty_perminvent_cell *cell;
struct obj *obj;
char invbuf[BUFSZ], *text, nxtlet;
int row, col, side, slot, maxslot;
winid window = g.perm_invent_win;
char invbuf[BUFSZ], *text;
boolean force_redraw = g.program_state.in_docrt ? TRUE : FALSE,
show_gold = (ttyinvmode & InvShowGold) != 0,
inuse_only = (ttyinvmode & InvInUse) != 0,
sparse = (ttyinvmode & InvSparse) != 0;
inuse_only = (ttyinvmode & InvInUse) != 0;
int rows_per_side = (!show_gold ? 26 : 27);
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;
slot_limit = SIZE(slot_tracker);
if (inuse_only) {
rows_per_side = cw->maxrow - 2; /* -2 top and bottom borders */
}
/* we just return if the window creation failed, probably due to
not meeting size requirements */
if (window == WIN_ERR)
return;
if (!iflags.perm_invent) {
if (done_tty_perm_invent_init) {
/* Odd - but this could be end-of-game disclosure
* which just sets boolean iflag.perm_invent to
* FALSE without actually doing anything else.
*/
tty_perm_invent_toggled(TRUE); /* TRUE means negated */
(void) doredraw();
}
return;
}
if ((cw = wins[window]) == (struct WinDesc *) 0)
panic(winpanicstr, window);
if (!done_tty_perm_invent_init) {
tty_invent_box_glyph_init(cw);
}
text = Empty; /* lint suppression */
maxslot = ((int) cw->maxrow - 2) * (!inuse_only ? 2 : 1);
obj = g.invent;
for (slot = 0; slot < 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 invbuf[] 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(invbuf, sizeof invbuf, "%c - %s", obj->invlet, text);
text = invbuf;
obj = obj->nobj; /* set up for next iteration */
} else if (sparse) {
Sprintf(invbuf, "%c", nxtlet); /* empty slot */
for (slot = 0; slot < slot_limit; ++slot)
if (slot_tracker[slot])
filled_count++;
for (slot = 0; slot < slot_limit; ++slot) {
if (slot_tracker[slot])
continue;
if (slot == 0 && !filled_count) {
Sprintf(invbuf, "%-4s[%s]", "",
!filled_count ? "empty"
: inuse_only ? "no items are in use"
: "only gold");
text = invbuf;
} else {
if (slot == 0) {
Sprintf(invbuf, "%-4s[%s]", "",
!g.invent ? "empty"
: inuse_only ? "no items are in use"
: "only gold");
text = invbuf;
} else {
text = Empty; /* "" => fill slot with spaces */
}
text = Empty; /* "" => fill slot with spaces */
}
row = (slot % (!show_gold ? 26 : 27)) + 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 = slot < (!show_gold ? 26 : 27) ? 0 : 1;
ttyinv_populate_slot(cw, row, side, text, 0);
side = slot < rows_per_side ? 0 : 1;
if (!(inuse_only && side == 1))
ttyinv_populate_slot(cw, row, side, text, 0);
}
/* has there been a glyph reset since we last got here? */
if (g.glyph_reset_timestamp > last_glyph_reset_when) {
// tty_invent_box_glyph_init(wins[WIN_INVEN]);
last_glyph_reset_when = g.glyph_reset_timestamp;
force_redraw = TRUE;
}
/* render to the display */
calling_from_update_inventory = TRUE;
/* 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);
tty_print_glyph(window, col + 1, row, cell->content.gi,
&nul_glyphinfo);
end_glyphout();
} else {
if (col != cw->curx || row != cw->cury)
@@ -3627,113 +3741,13 @@ tty_update_inventory(int arg UNUSED)
cell->refresh = 0;
}
}
tty_curs(window, 1, 0);
for (slot = 0; slot < SIZE(slot_tracker); ++slot)
slot_tracker[slot] = 0;
calling_from_update_inventory = FALSE;
#endif /* CORE_INVENT */
#endif /* TTY_PERM_INVENT */
return;
}
perminvent_info *
tty_update_invent_slot(
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;
}
ttyinvmode = pi->fromcore.invmode;
show_gold = (ttyinvmode & InvShowGold) != 0;
inuse_only = (ttyinvmode & InvInUse) != 0;
/* sparse isn't needed port-side */
switch(pi->fromcore.core_request) {
case request_settings:
pi->tocore = zero_tocore;
tty_ok = assesstty(ttyinvmode,
&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 */
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, pi->fromcore.clr);
break;
case render:
if ((cw = wins[window]) == (struct WinDesc *) 0)
panic(winpanicstr, window);
/* render to the display */
force_redraw = pi->fromcore.force_redraw;
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;
}
}
tty_curs(window, 1, 0);
ttyDisplay->curx = 1;
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
*/
@@ -3753,7 +3767,7 @@ assesstty(
*offy = 1 + ROWNO + 3; /* 3: + 2 + (iflags.wc2_statuslines > 2) */
*rows = (ttyDisplay->rows - (*offy));
*cols = ttyDisplay->cols;
*minrow = tty_pi_minrow;
*minrow = tty_perminv_minrow;
if (show_gold)
*minrow += 1;
/* "normal" max for items in use would be 3 weapon + 7 armor + 4
@@ -3767,7 +3781,7 @@ assesstty(
*minrow = 1 + 15 + 1; /* top border + 15 lines + bottom border */
*maxrow = *minrow;
*maxcol = *cols;
return !(*rows < *minrow || *cols < tty_pi_mincol);
return !(*rows < *minrow || *cols < tty_perminv_mincol);
}
/* put the formatted object description for one item into a particular row
@@ -3783,7 +3797,12 @@ ttyinv_populate_slot(
char c;
int ccnt, col, endcol;
col = bordercol[side] + 1;
/* FIXME: this needs a review. Crashed under InvInUse without */
if ((ttyinvmode & InvInUse) != 0)
col = bordercol[0] + 1;
else
col = bordercol[side] + 1;
endcol = bordercol[side + 1] - 1;
cell = &cw->cells[row][col];
if (cell->color != color)
@@ -3819,7 +3838,7 @@ tty_refresh_inventory(int start, int stop, int y)
{
int row = y, col, col_limit = stop;
struct WinDesc *cw = 0;
winid window = g.perm_invent_win;
winid window = WIN_INVEN;
struct tty_perminvent_cell *cell;
if (window == WIN_ERR || !iflags.perm_invent || y < 0)
@@ -3856,11 +3875,14 @@ RESTORE_WARNING_FORMAT_NONLITERAL
static void
tty_invent_box_glyph_init(struct WinDesc *cw)
{
{
int row, col;
uchar sym;
struct tty_perminvent_cell *cell;
if (cw == 0 || !cw->active)
return;
for (row = 0; row < cw->maxrow; ++row)
for (col = 0; col < cw->maxcol; ++col) {
cell = &cw->cells[row][col];
@@ -3927,9 +3949,16 @@ tty_invent_box_glyph_init(struct WinDesc *cw)
}
done_tty_perm_invent_init = TRUE;
}
#endif /* TTY_PERM_INVENT */
/* update persistent inventory window */
void
tty_update_inventory(int arg UNUSED)
{
/* currently not used */
return;
}
void
tty_mark_synch(void)
{
@@ -3972,8 +4001,8 @@ docorner(register int xmin, register int ymax, int ystart_between_menu_pages)
#ifdef TTY_PERM_INVENT
struct WinDesc *icw = 0;
if (g.perm_invent_win != WIN_ERR)
icw = wins[g.perm_invent_win];
if (WIN_INVEN != WIN_ERR)
icw = wins[WIN_INVEN];
#endif
HUPSKIP();

View File

@@ -120,7 +120,7 @@ struct window_procs mswin_procs = {
mswin_status_update,
genl_can_suspend_yes,
mswin_update_inventory,
mswin_update_invent_slot,
mswin_ctrl_nhwindow,
};
/*
@@ -1245,15 +1245,13 @@ mswin_update_inventory(int arg)
display_inventory(NULL, FALSE);
}
perminvent_info *
mswin_update_invent_slot(
winid window, /* window to use, must be of type NHW_MENU */
int inventory_slot, /* slot id: 0 - info return to core */
/* 1 - gold slot */
/* 2 - 29 obj slots */
perminvent_info *pi)
win_request_info *
mswin_ctrl_nhwindow(
winid window,
int request,
win_request_info *wri)
{
return (perminvent_info *) 0;
return (win_request_info *) 0;
}
/*

View File

@@ -193,7 +193,7 @@ void mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
boolean enable);
void mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks);
void mswin_update_inventory(int);
perminvent_info *mswin_update_invent_slot(winid, int, perminvent_info *);
win_request_info *mswin_ctrl_nhwindow(winid, int, win_request_info *);
/* helper function */
HWND mswin_hwnd_from_winid(winid wid);