From: PatR Date: Tue, 5 Jan 2021 02:01:49 +0000 (-0800) Subject: curses askname() X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a9a18fa2f332b37d707c64c076385db1eb77d23;p=nethack curses askname() Noticed when implementing restore-via-menu for curses a couple of days ago: The "Who are you?" prompt wouldn't let me cancel out via . I created a character named '\033' which was displayed as "^[" during play and produced a save file shown by 'ls' as "501?.Z". To fix this properly, we will need to replace use of wgetnstr() with something of our own. That's more work than I feel like tackling. This fakes ESC handling if the player is willing to type rather than just when terminating the prompt. --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 103848a39..5f8fafe54 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.418 $ $NHDT-Date: 1609642144 2021/01/03 02:49:04 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.420 $ $NHDT-Date: 1609811543 2021/01/05 01:52:23 $ General Fixes and Modified Features ----------------------------------- @@ -482,6 +482,11 @@ remove unused vision tables curses: 'msg_window' option wasn't functional for curses unless the binary also included tty support +curses: line input that doesn't take place on the bottom line of the message + window or in a popup doesn't support ESC to kill partial input or to + cancel; "Who are you?" prompt was willing to name a character "^["; + have askname() fake the usual ESC handling, but player has to type + for that to work Qt: at Xp levels above 20 with 'showexp' On, the combined status field "Level:NN/nnnnnnnn" was too big and truncated by a char at each end Qt: searching a text window for something that wasn't found and then searching diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index ba738db52..627147b28 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -240,21 +240,45 @@ curses_player_selection() void curses_askname() { + const char *bail_msg = "Until next time then..."; + int trylimit = 10; + #ifdef SELECTSAVED if (iflags.wc2_selectsaved && !iflags.renameinprogress) switch (restore_menu(MAP_WIN)) { - case -1: - curses_bail("Until next time then..."); /* quit */ - /*NOTREACHED*/ - case 0: - break; /* no game chosen; start new game */ - case 1: - return; /* g.plname[] has been set */ + case -1: /* quit */ + goto bail; + case 0: /* new game */ + break; + case 1: /* picked a save file to restore and set plname[] for it */ + return; } #endif /* SELECTSAVED */ - g.plname[0] = '\0'; - curses_line_input_dialog("Who are you?", g.plname, PL_NSIZ); + do { + if (--trylimit < 0) { + bail_msg = "A name is required; giving up."; + goto bail; + } + + g.plname[0] = '\0'; + /* for askname(), this will use wgetnstr() which treats ESC like + an ordinary character; fake the behavior we want: as kill_char + if it follows any input or as cancel if it is at the start; + player has to type to get back here though */ + curses_line_input_dialog("Who are you?", g.plname, PL_NSIZ); + + if (g.plname[0] == '\033') + goto bail; + (void) mungspaces(g.plname); + } while (!g.plname[0] || index(g.plname, '\033') != 0); + + /* we get here if input is non-empty and doesn't contain ESC */ + return; + + bail: + curses_bail(bail_msg); + /*NOTREACHED*/ }