Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2019-04-02 12:25:16 -04:00
33 changed files with 1126 additions and 660 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winmisc.c $NHDT-Date: 1543830350 2018/12/03 09:45:50 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.42 $ */
/* NetHack 3.6 winmisc.c $NHDT-Date: 1554135506 2019/04/01 16:18:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.44 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -41,6 +41,8 @@
static Widget extended_command_popup = 0;
static Widget extended_command_form;
static Widget *extended_commands = 0;
static const char **command_list;
static short *command_indx;
static int extended_cmd_selected; /* index of the selected command; */
static int ps_selected; /* index of selected role */
#define PS_RANDOM (-50)
@@ -50,6 +52,7 @@ static const char ps_randchars[] = "*@\n\rrR";
static const char ps_quitchars[] = "\033qQ";
#define EC_NCHARS 32
static boolean ec_full_list = FALSE;
static boolean ec_active = FALSE;
static int ec_nchars = 0;
static char ec_chars[EC_NCHARS];
@@ -111,13 +114,14 @@ XtPointer
i2xtp(i)
int i;
{
return (XtPointer)(long)i;
return (XtPointer) (ptrdiff_t) i;
}
int
xtp2i(x)
XtPointer x;
{
return (long)x;
return (int) (ptrdiff_t) x;
}
/* Player Selection ------------------------------------------------------- */
@@ -1581,9 +1585,16 @@ X11_player_selection()
}
}
/* called by core to have the player pick an extended command */
int
X11_get_ext_cmd()
{
if (iflags.extmenu != ec_full_list) {
/* player has toggled the 'extmenu' option, toss the old widgets */
if (extended_commands)
release_extended_cmds(); /* will set extended_commands to Null */
ec_full_list = iflags.extmenu;
}
if (!extended_commands)
init_extended_commands_popup();
@@ -1597,15 +1608,19 @@ X11_get_ext_cmd()
/* The callbacks will enable the event loop exit. */
(void) x_event(EXIT_ON_EXIT);
return extended_cmd_selected;
if (extended_cmd_selected < 0)
return -1;
return command_indx[extended_cmd_selected];
}
void
release_extended_cmds()
{
if (extended_commands) {
XtDestroyWidget(extended_command_popup);
XtDestroyWidget(extended_command_popup), extended_command_popup = 0;
free((genericptr_t) extended_commands), extended_commands = 0;
free((genericptr_t) command_list), command_list = (const char **) 0;
free((genericptr_t) command_indx), command_indx = (short *) 0;
}
}
@@ -1816,6 +1831,22 @@ int ec_indx; /* might be greater than extended_cmd_selected */
}
}
/* decide whether extcmdlist[idx] should be part of extended commands menu */
static boolean
ignore_extcmd(idx)
int idx;
{
/* #shell or #suspect might not be available;
'extmenu' option controls whether we show full list
or just the traditional extended commands */
if ((extcmdlist[idx].flags & CMD_NOT_AVAILABLE) != 0
|| ((extcmdlist[idx].flags & AUTOCOMPLETE) == 0 && !ec_full_list)
|| strlen(extcmdlist[idx].ef_txt) < 2) /* ignore "#" and "?" */
return TRUE;
return FALSE;
}
/* ARGSUSED */
void
ec_key(w, event, params, num_params)
@@ -1825,11 +1856,12 @@ String *params;
Cardinal *num_params;
{
char ch;
int i;
int pass;
int i, pass;
float shown, top;
Arg arg[2];
Widget hbar, vbar;
XKeyEvent *xkey = (XKeyEvent *) event;
nhUse(w);
nhUse(params);
nhUse(num_params);
@@ -1857,6 +1889,25 @@ Cardinal *num_params;
exit_x_event = TRUE; /* leave event loop */
ec_active = FALSE;
return;
} else if (ch == MENU_FIRST_PAGE || ch == MENU_LAST_PAGE) {
hbar = vbar = (Widget) 0;
find_scrollbars(w, &hbar, &vbar);
if (vbar) {
top = (ch == MENU_FIRST_PAGE) ? 0.0 : 1.0;
XtCallCallbacks(vbar, XtNjumpProc, &top);
}
return;
} else if (ch == MENU_NEXT_PAGE || ch == MENU_PREVIOUS_PAGE) {
hbar = vbar = (Widget) 0;
find_scrollbars(w, &hbar, &vbar);
if (vbar) {
XtSetArg(arg[0], nhStr(XtNshown), &shown);
XtSetArg(arg[1], nhStr(XtNtopOfThumb), &top);
XtGetValues(vbar, arg, TWO);
top += ((ch == MENU_NEXT_PAGE) ? shown : -shown);
XtCallCallbacks(vbar, XtNjumpProc, &top);
}
return;
}
/*
@@ -1886,19 +1937,14 @@ Cardinal *num_params;
if (extended_cmd_selected >= 0)
swap_fg_bg(extended_commands[extended_cmd_selected]);
extended_cmd_selected = -1; /* dismiss */
ec_chars[0] = ec_chars[ec_nchars-1];
ec_chars[0] = ec_chars[ec_nchars - 1];
ec_nchars = 1;
}
for (i = 0; extcmdlist[i].ef_txt; i++) {
if (extcmdlist[i].flags & CMD_NOT_AVAILABLE)
continue;
if (extcmdlist[i].ef_txt[0] == '?')
continue;
if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
for (i = 0; command_list[i]; ++i) {
if (!strncmp(ec_chars, command_list[i], ec_nchars)) {
if (extended_cmd_selected != i) {
/* I should use set() and unset() actions, but how do */
/* I send the an action to the widget? */
/* I should use set() and unset() actions, but how do
I send the an action to the widget? */
if (extended_cmd_selected >= 0)
swap_fg_bg(extended_commands[extended_cmd_selected]);
extended_cmd_selected = i;
@@ -1908,11 +1954,10 @@ Cardinal *num_params;
ambiguous choices, plus one to show thare aren't any
more such, will scroll into view */
do {
if (!extcmdlist[i + 1].ef_txt
|| *extcmdlist[i + 1].ef_txt == '?')
if (!command_list[i + 1])
break; /* end of list */
++i;
} while (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars));
} while (!strncmp(ec_chars, command_list[i], ec_nchars));
ec_scroll_to_view(i);
return;
@@ -1929,25 +1974,24 @@ static void
init_extended_commands_popup()
{
int i, j, num_commands, ignore_cmds = 0;
const char **command_list;
/* count commands */
for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++)
if (extcmdlist[num_commands].flags & CMD_NOT_AVAILABLE)
if (ignore_extcmd(num_commands))
++ignore_cmds;
/* If the last entry is "help", don't use it. */
if (strcmp(extcmdlist[num_commands - 1].ef_txt, "?") == 0)
--num_commands;
j = num_commands - ignore_cmds;
command_list = (const char **) alloc((unsigned) j * sizeof (char *));
command_list = (const char **) alloc((unsigned) (j * sizeof (char *) + 1));
command_indx = (short *) alloc((unsigned) (j * sizeof (short) + 1));
for (i = j = 0; i < num_commands; i++) {
if (extcmdlist[i].flags & CMD_NOT_AVAILABLE)
if (ignore_extcmd(i))
continue;
command_indx[j] = (short) i;
command_list[j++] = extcmdlist[i].ef_txt;
}
command_list[j] = (char *) 0;
command_indx[j] = -1;
num_commands = j;
extended_command_popup =
@@ -1955,8 +1999,6 @@ init_extended_commands_popup()
extended_command_translations, "dismiss", extend_dismiss,
"help", extend_help, num_commands, command_list,
&extended_commands, extend_select, &extended_command_form);
free((char *) command_list);
}
/* ------------------------------------------------------------------------ */

View File

@@ -17,6 +17,8 @@
#define strncasecmp strncmpi
#endif
extern long curs_mesg_suppress_turn; /* from cursmesg.c */
/*
* Note:
*
@@ -79,6 +81,7 @@ typedef struct nhm {
int height; /* Window height of menu */
int width; /* Window width of menu */
boolean reuse_accels; /* Non-unique accelerators per page */
boolean bottom_heavy; /* display multi-page menu starting at end */
struct nhm *prev_menu; /* Pointer to previous entry */
struct nhm *next_menu; /* Pointer to next entry */
} nhmenu;
@@ -89,6 +92,8 @@ typedef enum menu_op_type {
INVERT
} menu_op;
static nhmenu_item *curs_new_menu_item(winid, const char *);
static void curs_pad_menu(nhmenu *, boolean);
static nhmenu *get_menu(winid wid);
static char menu_get_accel(boolean first);
static void menu_determine_pages(nhmenu *menu);
@@ -120,6 +125,10 @@ curses_line_input_dialog(const char *prompt, char *answer, int buffer)
int height = prompt_height;
char input[BUFSZ];
/* if messages were being suppressed for the remainder of the turn,
re-activate them now that input is being requested */
curs_mesg_suppress_turn = -1;
if (buffer >= (int) sizeof input)
buffer = (int) sizeof input - 1;
maxwidth = term_cols - 2;
@@ -201,6 +210,10 @@ curses_character_input_dialog(const char *prompt, const char *choices,
boolean any_choice = FALSE;
boolean accept_count = FALSE;
/* if messages were being suppressed for the remainder of the turn,
re-activate them now that input is being requested */
curs_mesg_suppress_turn = -1;
if (g.invent || (g.moves > 1)) {
curses_get_window_size(MAP_WIN, &map_height, &map_width);
} else {
@@ -369,6 +382,7 @@ curses_ext_cmd()
starty = 0;
if (iflags.wc_popup_dialog) { /* Prompt in popup window */
int x0, y0, w, h; /* bounding coords of popup */
extwin2 = curses_create_window(25, 1, UP);
wrefresh(extwin2);
/* create window inside window to prevent overwriting of border */
@@ -513,6 +527,7 @@ curses_create_nhmenu(winid wid)
new_menu->height = 0;
new_menu->width = 0;
new_menu->reuse_accels = FALSE;
new_menu->bottom_heavy = FALSE;
return;
}
@@ -524,6 +539,7 @@ curses_create_nhmenu(winid wid)
new_menu->height = 0;
new_menu->width = 0;
new_menu->reuse_accels = FALSE;
new_menu->bottom_heavy = FALSE;
new_menu->next_menu = NULL;
if (nhmenus == NULL) { /* no menus in memory yet */
@@ -538,15 +554,38 @@ curses_create_nhmenu(winid wid)
}
}
static nhmenu_item *
curs_new_menu_item(winid wid, const char *str)
{
char *new_str;
nhmenu_item *new_item;
new_str = curses_copy_of(str);
curses_rtrim(new_str);
new_item = (nhmenu_item *) alloc((unsigned) sizeof (nhmenu_item));
new_item->wid = wid;
new_item->glyph = NO_GLYPH;
new_item->identifier = cg.zeroany;
new_item->accelerator = '\0';;
new_item->group_accel = '\0';
new_item->attr = 0;
new_item->str = new_str;
new_item->presel = FALSE;
new_item->selected = FALSE;
new_item->page_num = 0;
new_item->line_num = 0;
new_item->num_lines = 0;
new_item->count = -1;
new_item->next_item = NULL;
return new_item;
}
/* Add a menu item to the given menu window */
void
curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier,
curses_add_nhmenu_item(winid wid, int glyph, const ANY_P *identifier,
CHAR_P accelerator, CHAR_P group_accel, int attr,
const char *str, BOOLEAN_P presel)
{
char *new_str;
nhmenu_item *new_item, *current_items, *menu_item_ptr;
nhmenu *current_menu = get_menu(wid);
@@ -560,23 +599,13 @@ curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier,
return;
}
new_str = curses_copy_of(str);
curses_rtrim((char *) new_str);
new_item = (nhmenu_item *) alloc((unsigned) sizeof (nhmenu_item));
new_item->wid = wid;
new_item = curs_new_menu_item(wid, str);
new_item->glyph = glyph;
new_item->identifier = *identifier;
new_item->accelerator = accelerator;
new_item->group_accel = group_accel;
new_item->attr = attr;
new_item->str = new_str;
new_item->presel = presel;
new_item->selected = FALSE;
new_item->page_num = 0;
new_item->line_num = 0;
new_item->num_lines = 0;
new_item->count = -1;
new_item->next_item = NULL;
current_items = current_menu->entries;
menu_item_ptr = current_items;
@@ -593,6 +622,67 @@ curses_add_nhmenu_item(winid wid, int glyph, const ANY_P * identifier,
}
}
/* for menu->bottom_heavy -- insert enough blank lines at top of
first page to make the last page become a full one */
static void
curs_pad_menu(nhmenu *current_menu, boolean do_pad UNUSED)
{
nhmenu_item *menu_item_ptr;
int numpages = current_menu->num_pages;
/* caller has already called menu_win_size() */
menu_determine_pages(current_menu); /* sets 'menu->num_pages' */
numpages = current_menu->num_pages;
/* pad beginning of menu so that partial last page becomes full;
might be slightly less than full if any entries take multiple
lines and the padding would force those to span page boundary
and that gets prevented; so we re-count the number of pages
with every insertion instead of trying to calculate the number
of them to add */
do {
menu_item_ptr = curs_new_menu_item(current_menu->wid, "");
menu_item_ptr->next_item = current_menu->entries;
current_menu->entries->prev_item = menu_item_ptr;
current_menu->entries = menu_item_ptr;
current_menu->num_entries += 1;
menu_determine_pages(current_menu);
} while (current_menu->num_pages == numpages);
/* we inserted blank lines at beginning until final entry spilled
over to another page; take the most recent blank one back out */
current_menu->num_entries -= 1;
current_menu->entries = menu_item_ptr->next_item;
current_menu->entries->prev_item = (nhmenu_item *) 0;
free((genericptr_t) menu_item_ptr->str);
free((genericptr_t) menu_item_ptr);
/* reset page count; shouldn't need to re-count */
current_menu->num_pages = numpages;
return;
}
/* mark ^P message recall menu, for msg_window:full (FIFO), where we'll
start viewing on the last page so be able to see most recent immediately */
void
curs_menu_set_bottom_heavy(winid wid)
{
nhmenu *menu = get_menu(wid);
/*
* Called after end_menu + finalize_nhmenu,
* before select_menu + display_nhmenu.
*/
menu_win_size(menu); /* (normally not done until display_nhmenu) */
if (menu_is_multipage(menu, menu->width, menu->height)) {
menu->bottom_heavy = TRUE;
/* insert enough blank lines at top of first page to make the
last page become a full one */
curs_pad_menu(menu, TRUE);
}
return;
}
/* No more entries are to be added to menu, so details of the menu can be
finalized in memory */
@@ -689,8 +779,8 @@ curses_display_nhmenu(winid wid, int how, MENU_ITEM_P ** _selected)
}
if (count != num_chosen) {
impossible("curses_display_nhmenu: Selected items less than "
"expected number");
impossible(
"curses_display_nhmenu: Selected items less than expected number");
}
}
@@ -743,7 +833,7 @@ curses_del_menu(winid wid, boolean del_wid_too)
if ((tmpmenu = current_menu->prev_menu) != NULL) {
tmpmenu->next_menu = current_menu->next_menu;
} else {
nhmenus = current_menu->next_menu; /* New head mode or NULL */
nhmenus = current_menu->next_menu; /* New head node or NULL */
}
if ((tmpmenu = current_menu->next_menu) != NULL) {
tmpmenu->prev_menu = current_menu->prev_menu;
@@ -811,7 +901,7 @@ menu_is_multipage(nhmenu *menu, int width, int height)
int curline = 0;
nhmenu_item *menu_item_ptr = menu->entries;
if (strlen(menu->prompt) > 0) {
if (*menu->prompt) {
curline += curses_num_lines(menu->prompt, width) + 1;
}
@@ -854,7 +944,7 @@ menu_determine_pages(nhmenu *menu)
int page_end = height;
if (strlen(menu->prompt) > 0) {
if (*menu->prompt) {
curline += curses_num_lines(menu->prompt, width) + 1;
}
@@ -922,8 +1012,7 @@ menu_win_size(nhmenu *menu)
/* Add space for accelerator */
curentrywidth = strlen(menu_item_ptr->str) + 4;
#if 0 /* FIXME: menu glyphs */
if (menu_item_ptr->glyph != NO_GLYPH
&& iflags.use_menu_glyphs)
if (menu_item_ptr->glyph != NO_GLYPH && iflags.use_menu_glyphs)
curentrywidth += 2;
#endif
}
@@ -979,7 +1068,7 @@ static void
menu_display_page(nhmenu *menu, WINDOW * win, int page_num)
{
nhmenu_item *menu_item_ptr;
int count, curletter, entry_cols, start_col, num_lines, footer_x;
int count, curletter, entry_cols, start_col, num_lines;
char *tmpstr;
boolean first_accel = TRUE;
int color = NO_COLOR;
@@ -1102,20 +1191,25 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num)
}
if (menu->num_pages > 1) {
footer_x = menu->width - strlen("<- (Page X of Y) ->");
if (menu->num_pages > 9) { /* Unlikely */
footer_x -= 2;
int footer_x, footwidth, shoesize = menu->num_pages;
footwidth = (int) (sizeof "<- (Page X of Y) ->" - sizeof "");
while (shoesize >= 10) { /* possible for pickup from big piles... */
/* room for wider feet; extra digit for both X and Y */
footwidth += 2;
shoesize /= 10;
}
mvwprintw(win, menu->height, footer_x + 3, "(Page %d of %d)",
page_num, menu->num_pages);
footer_x = !menu->bottom_heavy ? (menu->width - footwidth) : 2;
if (page_num != 1) {
curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
mvwaddstr(win, menu->height, footer_x, "<=");
curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
}
mvwprintw(win, menu->height, footer_x + 2, " (Page %d of %d) ",
page_num, menu->num_pages);
if (page_num != menu->num_pages) {
curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
mvwaddstr(win, menu->height, menu->width - 2, "=>");
mvwaddstr(win, menu->height, footer_x + footwidth - 2, "=>");
curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
}
}
@@ -1132,13 +1226,13 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
int curletter;
int count = -1;
int count_letter = '\0';
int curpage = 1;
int curpage = !menu->bottom_heavy ? 1 : menu->num_pages;
int num_selected = 0;
boolean dismiss = FALSE;
char search_key[BUFSZ];
nhmenu_item *menu_item_ptr = menu->entries;
menu_display_page(menu, win, 1);
menu_display_page(menu, win, curpage);
while (!dismiss) {
curletter = getch();

View File

@@ -16,6 +16,7 @@ void curses_create_nhmenu(winid wid);
void curses_add_nhmenu_item(winid wid, int glyph, const ANY_P *identifier,
CHAR_P accelerator, CHAR_P group_accel, int attr,
const char *str, BOOLEAN_P presel);
void curs_menu_set_bottom_heavy(winid);
void curses_finalize_nhmenu(winid wid, const char *prompt);
int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected);
boolean curses_menu_exists(winid wid);

View File

@@ -9,6 +9,8 @@
#include "color.h"
#include "wincurs.h"
extern long curs_mesg_suppress_turn; /* from cursmesg.c */
/* Public functions for curses NetHack interface */
/* Interface definition, for windows.c */
@@ -72,8 +74,8 @@ struct window_procs curses_procs = {
curses_end_screen,
genl_outrip,
curses_preference_update,
genl_getmsghistory,
genl_putmsghistory,
curses_getmsghistory,
curses_putmsghistory,
curses_status_init,
curses_status_finish,
genl_status_enablefield,
@@ -687,6 +689,9 @@ curses_nhgetch()
{
int ch;
/* if messages are being suppressed, reenable them */
curs_mesg_suppress_turn = -1;
curses_prehousekeeping();
ch = curses_read_char();
curses_posthousekeeping();

View File

@@ -9,6 +9,10 @@
#include "cursmesg.h"
#include <ctype.h>
/* player can type ESC at More>> prompt to avoid seeing more messages
for the current move; but hero might get more than one move per turn,
so the input routines need to be able to cancel this */
long curs_mesg_suppress_turn = -1; /* also used in cursdial.c && cursmain.c */
/* Message window routines for curses interface */
@@ -46,16 +50,13 @@ curses_message_win_puts(const char *message, boolean recursed)
boolean border = curses_window_has_border(MESSAGE_WIN);
int message_length = strlen(message);
int border_space = 0;
static long suppress_turn = -1;
#if 1
#if 0
/*
* Handled by core's use of putstr(WIN_MESSAGE,ATR_NOHISTORY,message)
* for intermediate counts, but get_count() also uses putmsghistory()
* for the final count, to remember that without showing it. But
* curses is using genl_putmsghistory() which just delivers the text
* via a normal pline(). This hides that at cost of not having it
* in ^P recall and being out of sync with DUMPLOG's message history.
* This was useful when curses used genl_putmsghistory() but is not
* needed now that it has its own curses_putmsghistory() that's
* capable of putting something into the ^P recall history without
* displaying it at the same time.
*/
if (strncmp("Count:", message, 6) == 0) {
curses_count_window(message);
@@ -63,8 +64,8 @@ curses_message_win_puts(const char *message, boolean recursed)
}
#endif
if (suppress_turn == g.moves) {
return;
if (curs_mesg_suppress_turn == g.moves) {
return; /* user has typed ESC to avoid seeing remaining messages. */
}
curses_get_window_size(MESSAGE_WIN, &height, &width);
@@ -105,7 +106,7 @@ curses_message_win_puts(const char *message, boolean recursed)
/* Pause until key is hit - Esc suppresses any further
messages that turn */
if (curses_more() == '\033') {
suppress_turn = g.moves;
curs_mesg_suppress_turn = g.moves;
return;
}
} else {
@@ -156,6 +157,9 @@ curses_block(boolean noscroll) /* noscroll - blocking because of msgtype
WINDOW *win = curses_get_nhwin(MESSAGE_WIN);
const char *resp = " \r\n\033"; /* space, enter, esc */
/* if messages are being suppressed, reenable them */
curs_mesg_suppress_turn = -1;
curses_get_window_size(MESSAGE_WIN, &height, &width);
curses_toggle_color_attr(win, MORECOLOR, NONE, ON);
mvwprintw(win, my, mx, ">>");
@@ -309,6 +313,8 @@ curses_prev_mesg()
"[No past messages available.]", FALSE);
curses_end_menu(wid, "");
if (!do_lifo)
curs_menu_set_bottom_heavy(wid);
curses_select_menu(wid, PICK_NONE, &selected);
curses_del_wid(wid);
}
@@ -692,4 +698,99 @@ get_msg_line(boolean reverse, int mindex)
return current_mesg;
}
/* save/restore code retrieves one ^P message at a time during save and
puts it into save file; if any new messages are added to the list while
that is taking place, the results are likely to be scrambled */
char *
curses_getmsghistory(init)
boolean init;
{
static int nxtidx;
nhprev_mesg *mesg;
if (init)
nxtidx = 0;
else
++nxtidx;
if (nxtidx < num_messages) {
/* we could encode mesg->turn with the text of the message,
but then that text might need to be truncated, and more
significantly, restoring the save file with another
interface wouldn't know how find and decode or remove it;
likewise, restoring another interface's save file with
curses wouldn't find the expected turn info;
so, we live without that */
mesg = get_msg_line(FALSE, nxtidx);
} else
mesg = (nhprev_mesg *) 0;
return mesg ? mesg->str : (char *) 0;
}
/*
* This is called by the core savefile restore routines.
* Each time we are called, we stuff the string into our message
* history recall buffer. The core will send the oldest message
* first (actually it sends them in the order they exist in the
* save file, but that is supposed to be the oldest first).
* These messages get pushed behind any which have been issued
* during this session since they come from a previous session
* and logically precede anything (like "Restoring save file...")
* that's happened now.
*
* Called with a null pointer to finish up restoration.
*
* It's also called by the quest pager code when a block message
* has a one-line summary specified. We put that line directly
* into message history for ^P recall without having displayed it.
*/
void
curses_putmsghistory(msg, restoring_msghist)
const char *msg;
boolean restoring_msghist;
{
static boolean initd = FALSE;
static int stash_count;
static nhprev_mesg *stash_head = 0;
if (restoring_msghist && !initd) {
/* hide any messages we've gathered since starting current session
so that the ^P data will start out empty as we add ones being
restored from save file; we'll put these back after that's done */
stash_count = num_messages, num_messages = 0;
stash_head = first_mesg, first_mesg = (nhprev_mesg *) 0;
last_mesg = (nhprev_mesg *) 0; /* no need to remember the tail */
initd = TRUE;
}
if (msg) {
mesg_add_line(msg);
/* treat all saved and restored messages as turn #1 */
last_mesg->turn = 1L;
} else if (stash_count) {
nhprev_mesg *mesg;
long mesg_turn;
/* put any messages generated during the beginning of the current
session back; they logically follow any from the previous
session's save file */
while (stash_count > 0) {
/* we could manipulate the linked list directly but treating
stashed messages as newly occurring ones is much simpler;
we ignore the backlinks because the list is destroyed as it
gets processed hence there can't be any other traversals */
mesg = stash_head;
stash_head = mesg->next_mesg;
--stash_count;
mesg_turn = mesg->turn;
mesg_add_line(mesg->str);
last_mesg->turn = mesg_turn;
free((genericptr_t) mesg->str);
free((genericptr_t) mesg);
}
initd = FALSE; /* reset */
}
}
/*cursmesg.c*/

View File

@@ -18,5 +18,7 @@ void curses_last_messages(void);
void curses_init_mesg_history(void);
void curses_prev_mesg(void);
void curses_count_window(const char *count_text);
char *curses_getmsghistory(BOOLEAN_P);
void curses_putmsghistory(const char *, BOOLEAN_P);
#endif /* CURSMESG_H */

View File

@@ -25,6 +25,7 @@ extern boolean status_activefields[MAXBLSTATS];
static char *status_vals_long[MAXBLSTATS];
#ifdef STATUS_HILITES
static unsigned long *curses_colormasks;
static long curses_condition_bits;
static int curses_status_colors[MAXBLSTATS];
static int hpbar_percent, hpbar_color;
@@ -36,12 +37,11 @@ static int FDECL(condcolor, (long, unsigned long *));
static int FDECL(condattr, (long, unsigned long *));
static int FDECL(nhattr2curses, (int));
#endif /* STATUS_HILITES */
static void FDECL(draw_status, (unsigned long *));
static void FDECL(draw_vertical, (BOOLEAN_P, unsigned long *));
static void FDECL(draw_horizontal, (BOOLEAN_P, unsigned long *));
static void NDECL(draw_status);
static void FDECL(draw_vertical, (BOOLEAN_P));
static void FDECL(draw_horizontal, (BOOLEAN_P));
static void curs_HPbar(char *, int);
static void curs_stat_conds(int, int *, int *, unsigned long *,
char *, boolean *);
static void curs_stat_conds(int, int *, int *, char *, boolean *);
static void curs_vert_status_vals(int);
/* width of a single line in vertical status orientation (one field per line;
@@ -162,6 +162,7 @@ unsigned long *colormasks;
return;
if (fldidx == BL_CONDITION) {
curses_condition_bits = *condptr;
curses_colormasks = colormasks;
} else {
#ifndef TEXTCOLOR
color_and_attr = (color_and_attr & ~0x00FF) | NO_COLOR;
@@ -204,19 +205,13 @@ unsigned long *colormasks;
}
}
} else { /* BL_FLUSH */
if (!changed_fields && !g.context.botlx) {
; /* TODO: this isn't impossible but we want to track
* down the circumstances where it happens in order to
* minimize occurrences */
}
draw_status(colormasks);
draw_status();
changed_fields = 0;
}
}
void
draw_status(colormasks)
unsigned long *colormasks;
static void
draw_status()
{
WINDOW *win = curses_get_nhwin(STATUS_WIN);
int orient = curses_get_window_orientation(STATUS_WIN);
@@ -242,9 +237,9 @@ unsigned long *colormasks;
werase(win);
if (horiz)
draw_horizontal(border, colormasks);
draw_horizontal(border);
else
draw_vertical(border, colormasks);
draw_vertical(border);
if (border)
box(win, 0, 0);
@@ -252,10 +247,9 @@ unsigned long *colormasks;
}
/* horizontal layout on 2 or 3 lines */
void
draw_horizontal(border, colormasks)
static void
draw_horizontal(border)
boolean border;
unsigned long *colormasks;
{
#define blPAD BL_FLUSH
/* almost all fields already come with a leading space;
@@ -343,7 +337,7 @@ unsigned long *colormasks;
/* collect active conditions in cbuf[], space separated, suitable
for direct output if no highlighting is requested ('asis') but
primarily used to measure the length */
curs_stat_conds(0, &x, &y, colormasks, cbuf, &asis);
curs_stat_conds(0, &x, &y, cbuf, &asis);
clen = (int) strlen(cbuf);
cap_and_hunger = 0;
@@ -640,8 +634,7 @@ unsigned long *colormasks;
if (asis)
waddstr(win, cbuf);
else /* cond by cond if any cond specifies highlighting */
curs_stat_conds(0, &x, &y, colormasks,
(char *) 0, (boolean *) 0);
curs_stat_conds(0, &x, &y, (char *) 0, (boolean *) 0);
} /* curses_condition_bits */
} /* hitpointbar vs regular field vs conditions */
} /* i (fld) */
@@ -651,10 +644,9 @@ unsigned long *colormasks;
}
/* vertical layout, to left or right of map */
void
draw_vertical(border, colormasks)
static void
draw_vertical(border)
boolean border;
unsigned long *colormasks;
{
/* for blank lines, the digit prefix is the order in which they get
removed if we need to shrink to fit within height limit (very rare) */
@@ -893,8 +885,7 @@ unsigned long *colormasks;
if (cond_count) {
/* output active conditions, three per line;
cursor is already positioned where they should start */
curs_stat_conds(1, &x, &y, colormasks,
(char *) 0, (boolean *) 0);
curs_stat_conds(1, &x, &y, (char *) 0, (boolean *) 0);
}
} /* hitpointbar vs regular field vs conditions */
} /* fld loop */
@@ -971,7 +962,6 @@ extern const struct condmap valid_conditions[]; /* botl.c */
static void
curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
int *x, int *y, /* real for vertical, ignored otherwise */
unsigned long *colormasks, /* input */
char *condbuf, /* optional output; collect string of conds */
boolean *nohilite) /* optional output; indicates whether -*/
{ /*+ condbuf[] could be used as-is */
@@ -994,8 +984,8 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
Strcpy(condnam, valid_conditions[i].id);
Strcat(strcat(condbuf, " "), upstart(condnam));
if (nohilite && *nohilite
&& (condcolor(bitmsk, colormasks) != NO_COLOR
|| condattr(bitmsk, colormasks) != 0))
&& (condcolor(bitmsk, curses_colormasks) != NO_COLOR
|| condattr(bitmsk, curses_colormasks) != 0))
*nohilite = FALSE;
}
}
@@ -1034,12 +1024,14 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
if (!do_vert || (vert_cond % 3) != 1)
waddch(win, ' ');
if (iflags.hilite_delta) {
if ((attrmask = condattr(bitmsk, colormasks)) != 0) {
if ((attrmask = condattr(bitmsk, curses_colormasks))
!= 0) {
attrmask = nhattr2curses(attrmask);
wattron(win, attrmask);
}
#ifdef TEXTCOLOR
if ((color = condcolor(bitmsk, colormasks)) != NO_COLOR)
if ((color = condcolor(bitmsk, curses_colormasks))
!= NO_COLOR)
curses_toggle_color_attr(win, color, NONE, ON);
#endif
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 termcap.c $NHDT-Date: 1456907853 2016/03/02 08:37:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
/* NetHack 3.6 termcap.c $NHDT-Date: 1553858473 2019/03/29 11:21:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.29 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1206,12 +1206,37 @@ int n;
return nulstr;
}
/* suppress nonfunctional highlights so render_status() might be able to
optimize more; keep this in sync with s_atr2str() */
int
term_attr_fixup(msk)
int msk;
{
/* underline is converted to bold if its start sequence isn't available */
if ((msk & (1 << ATR_ULINE)) && !nh_US) {
msk |= (1 << ATR_BOLD);
msk &= ~(1 << ATR_ULINE);
}
/* blink is converted to bold unconditionally [why?] */
if (msk & (1 << ATR_BLINK)) {
msk |= (1 << ATR_BOLD);
msk &= ~(1 << ATR_BLINK);
}
/* dim is ignored */
if (msk & (1 << ATR_DIM))
msk &= ~(1 << ATR_DIM);
return msk;
}
void
term_start_attr(attr)
int attr;
{
if (attr) {
xputs(s_atr2str(attr));
const char *astr = s_atr2str(attr);
if (*astr)
xputs(s_atr2str(attr));
}
}
@@ -1220,7 +1245,10 @@ term_end_attr(attr)
int attr;
{
if (attr) {
xputs(e_atr2str(attr));
const char *astr = e_atr2str(attr);
if (*astr)
xputs(e_atr2str(attr));
}
}
@@ -1248,7 +1276,8 @@ void
term_start_color(color)
int color;
{
xputs(hilites[color]);
if (color < CLR_MAX)
xputs(hilites[color]);
}
/* not to be confused with has_colors() in unixtty.c */

File diff suppressed because it is too large Load Diff