]> granicus.if.org Git - nethack/commitdiff
curses askname()
authorPatR <rankin@nethack.org>
Tue, 5 Jan 2021 02:01:49 +0000 (18:01 -0800)
committerPatR <rankin@nethack.org>
Tue, 5 Jan 2021 02:01:49 +0000 (18:01 -0800)
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 <escape>.  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 <escape><return> rather than just <escape> when terminating
the prompt.

doc/fixes37.0
win/curses/cursmain.c

index 103848a398dfb683547e67ba9691214b277e09b0..5f8fafe5420020c4cc1f196fa76b00d82c5fc484 100644 (file)
@@ -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
+       <escape><return> 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
index ba738db52c591abfb3e6b70d4c2f1290b7a0f09d..627147b2818a59d63262748d77dbee84aa32b8a9 100644 (file)
@@ -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 <escape><return> 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*/
 }