diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 1bd82a925..5b177c06e 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.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 @@ -168,6 +173,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 @@ -187,6 +194,9 @@ 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 +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/include/wincurs.h b/include/wincurs.h index 18b3be289..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 @@ -169,6 +163,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/src/invent.c b/src/invent.c index 8e0d9f1de..03dea621e 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. */ @@ -2540,12 +2540,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 */ @@ -2637,6 +2637,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", @@ -2651,7 +2652,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 */ @@ -2727,6 +2728,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; diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 5a09de905..cf6374e5e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -648,7 +648,7 @@ DLB = #========================================== {$(WCURSES)}.c{$(OBJ)}.o: - @$(cc) $(PDCINCL) $(cflagsBuild) -Fo$@ $< + @$(cc) -DPDC_NCMOUSE $(PDCINCL) $(cflagsBuild) -Fo$@ $< #{$(WCURSES)}.txt{$(DAT)}.txt: # @copy $< $@ diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index c445c01fc..6d2bed525 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) { @@ -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; @@ -388,7 +389,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 +987,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 +1029,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 +1045,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 +1058,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); } diff --git a/win/curses/cursinit.c b/win/curses/cursinit.c index deda96ab8..366454150 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/cursmain.c b/win/curses/cursmain.c index 8f43387d5..1cc97815e 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -26,6 +26,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) @@ -906,6 +909,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 747b05c2a..441bda3d2 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,12 +891,21 @@ 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) { + 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 + * 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)) { - key = 0; /* Flag mouse click */ - *mousex = event.x; + 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; if (curses_window_has_border(MAP_WIN)) { @@ -897,7 +913,8 @@ curses_get_mouse(int *mousex, int *mousey, int *mod) (*mousey)--; } - *mod = CLICK_1; + *mod = ((event.bstate & (BUTTON1_CLICKED | BUTTON_CTRL)) + == BUTTON1_CLICKED) ? CLICK_1 : CLICK_2; } } } @@ -906,6 +923,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 = MOUSEBUTTONS; /* buttons 1, 2, and 3 */ + + 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 */