From aada9e270652489d0fa7b08e341489bc16cfca91 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 26 Jun 2019 15:46:44 -0700 Subject: [PATCH 1/8] mouse_support for win/curses using ncurses --- doc/fixes36.3 | 1 + include/wincurs.h | 1 + win/curses/cursmain.c | 5 +++++ win/curses/cursmisc.c | 51 +++++++++++++++++++++++++++++++++++++++---- win/curses/cursmisc.h | 1 + 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 8d778b1c9..0d01a0bd6 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -185,6 +185,7 @@ classify sources as released, beta, or work-in-progress via NH_DEVEL_STATUS if you reach the edge of a level (relatively uncommon) and try to move off, report that you can't go farther if the 'mention_walls' option is set wizard-mode: display effect to show where an unseen wished-for monster landed +curses: enable latent mouse support for ncurses; status for PDCurses unknown curses+'perm_invent': since persistent inventory is narrow, strip off "a", "an", or "the" prefix on inventory entries shown there so that a tiny bit more of the interesting portion is visible diff --git a/include/wincurs.h b/include/wincurs.h index 18b3be289..79122430d 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -169,6 +169,7 @@ extern int curses_read_attrs(const char *attrs); extern char *curses_fmt_attrs(char *); extern int curses_convert_keys(int key); extern int curses_get_mouse(int *mousex, int *mousey, int *mod); +extern void curses_mouse_support(int); /* cursdial.c */ diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index 0b36d5622..7094d316d 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -17,6 +17,9 @@ extern long curs_mesg_suppress_turn; /* from cursmesg.c */ struct window_procs curses_procs = { "curses", (WC_ALIGN_MESSAGE | WC_ALIGN_STATUS | WC_COLOR | WC_HILITE_PET +#ifdef NCURSES_MOUSE_VERSION /* (this macro name works for PDCURSES too) */ + | WC_MOUSE_SUPPORT +#endif | WC_PERM_INVENT | WC_POPUP_DIALOG | WC_SPLASH_SCREEN), (WC2_DARKGRAY | WC2_HITPOINTBAR #if defined(STATUS_HILITES) @@ -893,6 +896,8 @@ curses_preference_update(const char *pref) redo_status = TRUE; else if (!strcmp(pref, "align_message")) redo_main = TRUE; + else if (!strcmp(pref, "mouse_support")) + curses_mouse_support(iflags.wc_mouse_support); if (redo_main || redo_status) curs_reset_windows(redo_main, redo_status); diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index f7f08913b..51bd70208 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -885,11 +885,36 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) MEVENT event; if (getmouse(&event) == OK) { /* When the user clicks left mouse button */ - if (event.bstate & BUTTON1_CLICKED) { + if (event.bstate & (BUTTON1_CLICKED | BUTTON2_CLICKED)) { + /* + * The ncurses man page documents wmouse_trafo() incorrectly. + * It says that last argument 'TRUE' translates from screen + * to window and 'FALSE' translates from window to screen, + * but those are backwards. The mouse_trafo() macro calls + * last argument 'to_screen', suggesting that the backwards + * implementation is the intended behavior and the man page + * is describing it wrong. + */ /* See if coords are in map window & convert coords */ - if (wmouse_trafo(mapwin, &event.y, &event.x, TRUE)) { + if (wmouse_trafo(mapwin, &event.y, &event.x, +#ifdef PDCURSES + /* + * Not sure whether PDCurses matches the ncurses implementation + * or the ncurses documentation, so keep the 'bad' argument for + * it until we find out. [Mouse can be used successfully with + * 'bad' coordinate translation via align_message:bottom (and + * avoiding align_status:left) so that the subset of the screen + * corresponding to the map needs no translation. Adding instead + * of subtracting or vice versa makes no difference when amount + * involved is 0.] + */ + TRUE +#else + FALSE +#endif + )) { key = 0; /* Flag mouse click */ - *mousex = event.x; + *mousex = event.x + 1; /* +1: screen 0..78 is map 1..79 */ *mousey = event.y; if (curses_window_has_border(MAP_WIN)) { @@ -897,7 +922,7 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) (*mousey)--; } - *mod = CLICK_1; + *mod = (event.bstate & BUTTON1_CLICKED) ? CLICK_1 : CLICK_2; } } } @@ -906,6 +931,24 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) return key; } +void +curses_mouse_support(mode) +int mode; /* 0: off, 1: on, 2: alternate on */ +{ +#ifdef NCURSES_MOUSE_VERSION + mmask_t result, oldmask, newmask; + + if (!mode) + newmask = 0; + else + newmask = BUTTON1_CLICKED | BUTTON2_CLICKED; + + result = mousemask(newmask, &oldmask); + nhUse(result); +#else + nhUse(mode); +#endif +} static int parse_escape_sequence(void) diff --git a/win/curses/cursmisc.h b/win/curses/cursmisc.h index c964878af..0c871e35f 100644 --- a/win/curses/cursmisc.h +++ b/win/curses/cursmisc.h @@ -30,5 +30,6 @@ int curses_read_attrs(const char *attrs); char *curses_fmt_attrs(char *); int curses_convert_keys(int key); int curses_get_mouse(int *mousex, int *mousey, int *mod); +void curses_mouse_support(int); #endif /* CURSMISC_H */ From 56387dccb6f4865e083ebe2b1375e315655a5b7e Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 27 Jun 2019 15:02:49 -0700 Subject: [PATCH 2/8] curses mouse right-click Right button is button3 rather than button2. Accept either and treat both as "not left" to pass CLICK_2 back to the core. Treat +left-click as "not left" too, to simplify usage with Mac one-button mouse (where +left-click can be configured to send "secondary click" but might not be set do so) or one-button laptop trackpad (where having two fingers on the scrolling portion of the pad while clicking the button is necessary to send "secondary click"). --- win/curses/cursinit.c | 4 +++- win/curses/cursmisc.c | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/win/curses/cursinit.c b/win/curses/cursinit.c index 728f1e8ea..de8730fb5 100644 --- a/win/curses/cursinit.c +++ b/win/curses/cursinit.c @@ -838,8 +838,10 @@ curses_init_options() #ifdef NCURSES_MOUSE_VERSION if (iflags.wc_mouse_support) { - mousemask(BUTTON1_CLICKED, NULL); + curses_mouse_support(iflags.wc_mouse_support); } +#else + iflags.wc_mouse_support = 0; #endif } diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index 51bd70208..0d477a0a1 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -870,6 +870,13 @@ curses_convert_keys(int key) return ret; } +/* we treat buttons 2 and 3 as equivalent so that it doesn't matter which + one is for right-click and which for middle-click; the core uses CLICK_2 + for right-click ("not left" click) even though 2 might be middle button; + we also support Ctrl+left-click as another way to get "not left" click + since Mac is traditionally saddled with a one button mouse or trackpad */ +#define MOUSEBUTTONS ((BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED) \ + | BUTTON_CTRL) /* Process mouse events. Mouse movement is processed until no further mouse movement events are available. Returns 0 for a mouse click @@ -884,8 +891,8 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) #ifdef NCURSES_MOUSE_VERSION MEVENT event; - if (getmouse(&event) == OK) { /* When the user clicks left mouse button */ - if (event.bstate & (BUTTON1_CLICKED | BUTTON2_CLICKED)) { + if (getmouse(&event) == OK) { /* True if user has clicked */ + if ((event.bstate & MOUSEBUTTONS) != 0) { /* * The ncurses man page documents wmouse_trafo() incorrectly. * It says that last argument 'TRUE' translates from screen @@ -903,17 +910,16 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) * or the ncurses documentation, so keep the 'bad' argument for * it until we find out. [Mouse can be used successfully with * 'bad' coordinate translation via align_message:bottom (and - * avoiding align_status:left) so that the subset of the screen - * corresponding to the map needs no translation. Adding instead - * of subtracting or vice versa makes no difference when amount - * involved is 0.] + * avoiding align_status:top or left) so that the subset of the + * screen corresponding to the map needs no translation. Adding + * instead of subtracting makes no difference when amount is 0.] */ TRUE #else FALSE #endif )) { - key = 0; /* Flag mouse click */ + key = '\0'; /* core uses this to detect a mouse click */ *mousex = event.x + 1; /* +1: screen 0..78 is map 1..79 */ *mousey = event.y; @@ -922,7 +928,8 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) (*mousey)--; } - *mod = (event.bstate & BUTTON1_CLICKED) ? CLICK_1 : CLICK_2; + *mod = ((event.bstate & (BUTTON1_CLICKED | BUTTON_CTRL)) + == BUTTON1_CLICKED) ? CLICK_1 : CLICK_2; } } } @@ -941,7 +948,7 @@ int mode; /* 0: off, 1: on, 2: alternate on */ if (!mode) newmask = 0; else - newmask = BUTTON1_CLICKED | BUTTON2_CLICKED; + newmask = MOUSEBUTTONS; /* buttons 1, 2, and 3 */ result = mousemask(newmask, &oldmask); nhUse(result); From bd2cd75f7a8b3d9e1a77b5aa1be0cc587abb9846 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 27 Jun 2019 23:12:06 -0400 Subject: [PATCH 3/8] PDCurses requires PDC_NCMOUSE for compatibility with ncurses The PDC_NCMOUSE has to be defined on the command line or above the #include entries in win/curses/cursmisc.c. This does the former command line change. --- include/wincurs.h | 6 ------ sys/winnt/Makefile.msc | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/include/wincurs.h b/include/wincurs.h index 79122430d..127cd0faf 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -38,12 +38,6 @@ extern WINDOW *mapwin, *statuswin, *messagewin; /* Main windows */ #endif /* !__APPLE__ && !PDCURSES */ #define CURSES_DARK_GRAY 17 #define MAP_SCROLLBARS -#ifdef PDCURSES -# define getmouse nc_getmouse -# ifndef NCURSES_MOUSE_VERSION -# define NCURSES_MOUSE_VERSION -# endif -#endif #if !defined(A_LEFTLINE) && defined(A_LEFT) #define A_LEFTLINE A_LEFT diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index d2dd88414..fb8cd9b7e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -634,7 +634,7 @@ DLB = #========================================== {$(WCURSES)}.c{$(OBJ)}.o: - @$(cc) $(PDCINCL) $(cflagsBuild) -Fo$@ $< + @$(cc) -DPDC_NCMOUSE $(PDCINCL) $(cflagsBuild) -Fo$@ $< #{$(WCURSES)}.txt{$(DAT)}.txt: # @copy $< $@ From 39eed81aa2cb5823fb3ea4603828817e46a12339 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 27 Jun 2019 23:22:34 -0400 Subject: [PATCH 4/8] PDCurses behaves the same as ncurses --- win/curses/cursmisc.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index 0d477a0a1..5dcbe6d92 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -903,22 +903,7 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) * is describing it wrong. */ /* See if coords are in map window & convert coords */ - if (wmouse_trafo(mapwin, &event.y, &event.x, -#ifdef PDCURSES - /* - * Not sure whether PDCurses matches the ncurses implementation - * or the ncurses documentation, so keep the 'bad' argument for - * it until we find out. [Mouse can be used successfully with - * 'bad' coordinate translation via align_message:bottom (and - * avoiding align_status:top or left) so that the subset of the - * screen corresponding to the map needs no translation. Adding - * instead of subtracting makes no difference when amount is 0.] - */ - TRUE -#else - FALSE -#endif - )) { + if (wmouse_trafo(mapwin, &event.y, &event.x, FALSE)) { key = '\0'; /* core uses this to detect a mouse click */ *mousex = event.x + 1; /* +1: screen 0..78 is map 1..79 */ *mousey = event.y; From 119f0365f7994a28b4bcce93d31909f7fc2ef60a Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 28 Jun 2019 03:17:25 -0700 Subject: [PATCH 5/8] curses mouse_support bit for fixes36.3 --- doc/fixes36.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 89b9b58b5..7df9c7c55 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.72 $ $NHDT-Date: 1561681080 2019/06/28 00:18:00 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.74 $ $NHDT-Date: 1561717038 2019/06/28 10:17:18 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -187,7 +187,7 @@ classify sources as released, beta, or work-in-progress via NH_DEVEL_STATUS if you reach the edge of a level (relatively uncommon) and try to move off, report that you can't go farther if the 'mention_walls' option is set wizard-mode: display effect to show where an unseen wished-for monster landed -curses: enable latent mouse support for ncurses; status for PDCurses unknown +curses: enable latent mouse support curses+'perm_invent': since persistent inventory is narrow, strip off "a", "an", or "the" prefix on inventory entries shown there so that a tiny bit more of the interesting portion is visible From 2145387ac82ab97007f33d50164f9076d89a2e05 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 28 Jun 2019 11:59:14 -0700 Subject: [PATCH 6/8] curses menu and text window size Make final inventory disclosure use a full width menu instead of the default 38-column width with lots of wrapping. Also, increase that default from 38 to 40 for the rest of the time. Commit 9f6588af49766c00998291ff79735922199c8563 made the 38 vs 40 portion matter much less but I decided to keep it in anyway. When a menu or 'things that are here' popup has only a couple of lines and they happen to be narrow, a sized-to-fit window isn't always easy to spot when it is shown over the ends of old messages rather than over the map, even with a border box around it. Give such windows a minimum size of 5x25 so that they always stand out enough to be immediately seen. This will cause more message text to be rewritten occasionally (after dismissing the menu or text window) but the curses interface seems to discount that as something to be concerned about. --- doc/fixes36.3 | 4 +++- win/curses/cursdial.c | 44 ++++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 7df9c7c55..b27d8e64b 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.74 $ $NHDT-Date: 1561717038 2019/06/28 10:17:18 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.75 $ $NHDT-Date: 1561748351 2019/06/28 18:59:11 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -188,6 +188,8 @@ if you reach the edge of a level (relatively uncommon) and try to move off, report that you can't go farther if the 'mention_walls' option is set wizard-mode: display effect to show where an unseen wished-for monster landed curses: enable latent mouse support +curses: give menus and text windows a minimum size of 5x25 since tiny ones can + sometimes be overlooked when shown over old messages rather than map curses+'perm_invent': since persistent inventory is narrow, strip off "a", "an", or "the" prefix on inventory entries shown there so that a tiny bit more of the interesting portion is visible diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index a1058d802..793e6d81c 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -135,7 +135,7 @@ curses_line_input_dialog(const char *prompt, char *answer, int buffer) curses_got_input(); if (buffer > (int) sizeof input) - buffer = (int) sizeof input; + buffer = (int) sizeof input; maxwidth = term_cols - 2; if (iflags.window_inited) { @@ -388,7 +388,8 @@ curses_ext_cmd() getbegyx(extwin2, y0, x0); getmaxyx(extwin2, h, w); extwin = newwin(1, w - 2, y0 + 1, x0 + 1); - if (w - 4 < maxlen) maxlen = w - 4; + if (w - 4 < maxlen) + maxlen = w - 4; } else { curses_get_window_xy(MESSAGE_WIN, &winx, &winy); curses_get_window_size(MESSAGE_WIN, &messageh, &messagew); @@ -985,14 +986,24 @@ menu_determine_pages(nhmenu *menu) static void menu_win_size(nhmenu *menu) { - int width, height, maxwidth, maxheight, curentrywidth, lastline; + int maxwidth, maxheight, curentrywidth, lastline; int maxentrywidth = (int) strlen(menu->prompt); int maxheaderwidth = 0; nhmenu_item *menu_item_ptr; - maxwidth = 38; /* Reasonable minimum usable width */ - if ((term_cols / 2) > maxwidth) { - maxwidth = (term_cols / 2); /* Half the screen */ + if (program_state.gameover) { + /* for final inventory disclosure, use full width */ + maxwidth = term_cols - 2; + } else { + /* this used to be 38, which is 80/2 - 2 (half a 'normal' sized + screen minus room for a border box), but some data files + have been manually formatted for 80 columns (usually limited + to 78 but sometimes 79, rarely 80 itself) and using a value + less that 40 meant that a full line would wrap twice: + 1..38, 39..76, and 77..80 */ + maxwidth = 40; /* Reasonable minimum usable width */ + if ((term_cols / 2) > maxwidth) + maxwidth = (term_cols / 2); /* Half the screen */ } maxheight = menu_max_height(); @@ -1017,7 +1028,8 @@ menu_win_size(nhmenu *menu) } } - /* If widest entry is smaller than maxwidth, reduce maxwidth accordingly */ + /* If widest entry is smaller than maxwidth, reduce maxwidth + accordingly (but not too far; minimum width will be applied below) */ if (maxentrywidth < maxwidth) { maxwidth = maxentrywidth; } @@ -1032,8 +1044,6 @@ menu_win_size(nhmenu *menu) maxwidth = term_cols - 2; } - width = maxwidth; - /* Possibly reduce height if only 1 page */ if (!menu_is_multipage(menu, maxwidth, maxheight)) { menu_item_ptr = menu->entries; @@ -1047,16 +1057,16 @@ menu_win_size(nhmenu *menu) if (lastline < maxheight) { maxheight = lastline; } - } else { /* If multipage, make sure we have enough width for page footer */ - - if (width < 20) { - width = 20; - } } - height = maxheight; - menu->width = width; - menu->height = height; + /* avoid a tiny popup window; when it's shown over the endings of + old messsages rather than over the map, it is fairly easy for + the player to overlook it, particularly when walking around and + stepping on a pile of 2 items; also, multi-page menus need enough + room for "(Page M of N) => " even if all entries are narrower + than that; we specify same minimum width even when single page */ + menu->width = max(maxwidth, 25); + menu->height = max(maxheight, 5); } From bed5570e3baaa4c5203014e76ec9f2edc38c7e3b Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 28 Jun 2019 12:28:40 -0700 Subject: [PATCH 7/8] curses popup single char input With 'popup_dialog' On, a one line popup with question and likely responses and default answer was shown, but without having the cursor displayed at the end of emphasize that it was waiting for an answer. Make the popup be one character wider so that there is room to show the cursor. No effect when 'popup_dialog' is Off and prompts are shown at the bottom of the message window; those already have the cursor sitting at the end. --- doc/fixes36.3 | 4 +++- win/curses/cursdial.c | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index b27d8e64b..a46c815b8 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.75 $ $NHDT-Date: 1561748351 2019/06/28 18:59:11 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.76 $ $NHDT-Date: 1561750114 2019/06/28 19:28:34 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -168,6 +168,8 @@ curses+'perm_invent': if too many entries for window height, last one which curses+'perm_invent': top line was wasted (left blank) when borders Off curses+'perm_invent': don't highlight inventory letters since nothing is selectable from the menu comprising the persistent inventory window +curses+'popup_dialog': show the text cursor at the end of prompts for single + character input curses+EDIT_GETLIN: when a prompt's answer was preloaded, using ESC to discard it deleted it from the answer buffer but didn't erase it from screen tty: re-do one optimization used when status conditions have all been removed diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index 793e6d81c..ccd962fc1 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -264,7 +264,8 @@ curses_character_input_dialog(const char *prompt, const char *choices, any_choice = TRUE; } - prompt_width = (int) strlen(askstr); + /* +1: room for a trailing space where the cursor will rest */ + prompt_width = (int) strlen(askstr) + 1; if ((prompt_width + 2) > maxwidth) { prompt_height = curses_num_lines(askstr, maxwidth); @@ -284,11 +285,11 @@ curses_character_input_dialog(const char *prompt, const char *choices, /* TODO: add SUPPRESS_HISTORY flag, then after getting a response, append it and use put_msghistory() on combined prompt+answer */ custompline(OVERRIDE_MSGTYPE, "%s", askstr); - curs_set(1); } /*curses_stupid_hack = 0; */ + curs_set(1); while (1) { #ifdef PDCURSES answer = wgetch(message_window); @@ -342,6 +343,7 @@ curses_character_input_dialog(const char *prompt, const char *choices, if (choices != NULL && answer != '\0' && index(choices, answer)) break; } + curs_set(0); if (iflags.wc_popup_dialog) { /* Kludge to make prompt visible after window is dismissed @@ -354,7 +356,6 @@ curses_character_input_dialog(const char *prompt, const char *choices, curses_destroy_win(askwin); } else { curses_clear_unhighlight_message_window(); - curs_set(0); } return answer; From 701356341516334d1d6deabb884becf3ced1c03d Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 28 Jun 2019 12:50:08 -0700 Subject: [PATCH 8/8] ^I vs perm_invent again A recent fix for #wizidentify showing "Not carrying anything" after listing inventory items still showed "Not carrying anything" after "(all items are already identified)". Fix is easy. Trickier bug was that ^I performs object ID on selected items while the inventory routine is still in progress (but after it has processed every item) and the ID routine will call update_inventory() which will call the inventory routine to reformat invent. So the inventory display routine was called recursively without having returned to wizidentify where iflags.override_ID gets cleared to revert to normal inventory. The nested call was unintentionally narrowing the contents of persistent inventory window to whatever items were still unIDed. (Any inventory update, including ^R, restored it to full inventory.) --- doc/fixes36.3 | 7 ++++++- src/invent.c | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index a46c815b8..5b177c06e 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.76 $ $NHDT-Date: 1561750114 2019/06/28 19:28:34 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.77 $ $NHDT-Date: 1561751390 2019/06/28 19:49:50 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -86,6 +86,9 @@ partly eaten food with one bite left had message anomalies when eaten; the resulted in no messages at all when restarting and finishing last bite wizard mode ^I menu could list "Not carrying anything" after inventory items if perm_invent option was On (even on tty where that's not supported) +wizard mode ^I with 'perm_invent' On would unintentionally filter the content + of the persistent inventory window to unIDed items if any item got + chosen to be identified (^R would fix it, as would any invent change) change #adjust to treat carrying only gold as not having anything to adjust saving bones with 'perm_invent' On could result in "Bad fruit #N" warnings update persistent inventory window immediately if 'sortpack' option is toggled @@ -103,6 +106,8 @@ for wizard mode 'wizweight' option, glob weight wasn't shown unless glob had shop price information attached fix for feedback when a monster plays a fire horn at self to cure green slime ended up being used for zapping a wand of fire at self too +wizard mode ^I "not carrying anything" still claimed "not carrying anything" + if "(all items are already identified)" was given curses: sometimes the message window would show a blank line after a prompt curses: the change to show map in columns 1..79 instead of 2..80 made the highlight for '@' show up in the wrong place if clipped map had been diff --git a/src/invent.c b/src/invent.c index a4175e2a8..fc76a57a4 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1561314651 2019/06/23 18:30:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.259 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1561751391 2019/06/28 19:49:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.260 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2550,12 +2550,12 @@ long *out_cnt; menu_item *selected; unsigned sortflags; Loot *sortedinvent, *srtinv; - boolean wizid = FALSE, gotsomething = FALSE; + boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE; if (lets && !*lets) lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */ - if (iflags.perm_invent && (lets || xtra_choice)) { + if (iflags.perm_invent && (lets || xtra_choice || wizid)) { /* 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 */ @@ -2647,6 +2647,7 @@ long *out_cnt; add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "(all items are permanently identified already)", MENU_UNSELECTED); + gotsomething = TRUE; } else { any.a_obj = &wizid_fakeobj; Sprintf(prompt, "select %s to permanently identify", @@ -2661,7 +2662,7 @@ long *out_cnt; visctrl(iflags.override_ID)); add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE, prompt, MENU_UNSELECTED); - wizid = gotsomething = TRUE; + gotsomething = TRUE; } } else if (xtra_choice) { /* wizard override ID and xtra_choice are mutually exclusive */ @@ -2737,6 +2738,10 @@ long *out_cnt; if (wizid) { int i; + /* identifying items will update perm_invent, calling this + routine recursively, and we don't want the nested call + to filter on unID'd items */ + iflags.override_ID = 0; ret = '\0'; for (i = 0; i < n; ++i) { otmp = selected[i].item.a_obj;