]> granicus.if.org Git - nethack/commitdiff
fix for urgent messages for tty
authorPatR <rankin@nethack.org>
Mon, 20 Dec 2021 16:16:13 +0000 (08:16 -0800)
committerPatR <rankin@nethack.org>
Mon, 20 Dec 2021 16:16:13 +0000 (08:16 -0800)
If messages aren't currently being skipped due to --More--ESC when a
message flagged as urgent is issued and that urgent message itself
triggers --More-- to have the user acknowledge the previous message,
and the user types ESC at this new --More--, message suppression
starts.  With the overly simplistic existing code from a few days
ago, it was too late for the current message to override that.  Since
the urgent message gets buffered like any other (until another message
needs the top line or until input is needed), it wouldn't be shown
when the next message came along and discovered suppression in effect.

I'm not sure that all the changes here are necessary; there was some
flailing about involved.  But it seems to behave as intended now.

include/wintty.h
win/tty/topl.c
win/tty/wintty.c

index 2c1e63046d2f75faae837e74dfa4f9d6ad62d00f..eeb87b78c8e3b930d54be2a77c76ec4c2c96ed9a 100644 (file)
@@ -49,8 +49,13 @@ struct WinDesc {
 
 /* window flags */
 #define WIN_CANCELLED 1
-#define WIN_STOP 1        /* for NHW_MESSAGE; stops output */
+#define WIN_STOP 1        /* for NHW_MESSAGE; stops output; sticks until
+                           * next input request or reversed by WIN_NOSTOP */
 #define WIN_LOCKHISTORY 2 /* for NHW_MESSAGE; suppress history updates */
+#define WIN_NOSTOP 4      /* current message has been designated as urgent;
+                           * prevents WIN_STOP from becoming set if current
+                           * message triggers --More-- and user types ESC
+                           * (current message won't have been seen yet) */
 
 /* topline states */
 #define TOPLINE_EMPTY          0 /* empty */
index e4bbdc509c32ad470f4a6026cb2edf1e4b9f6992..38e556ebc0068328b4f19d17940c941c24ad3411 100644 (file)
@@ -144,7 +144,12 @@ show_topl(const char *str)
 {
     struct WinDesc *cw = wins[WIN_MESSAGE];
 
-    if (!(cw->flags & WIN_STOP)) {
+    /* show if either STOP isn't set or current message specifies NOSTOP */
+    if ((cw->flags & (WIN_STOP | WIN_NOSTOP)) != WIN_STOP) {
+        /* NOSTOP cancels persistent STOP and is a one-shot operation;
+           force both to be cleared (no-op for either bit that isn't set) */
+        cw->flags &= ~(WIN_STOP | WIN_NOSTOP);
+
         if (ttyDisplay->cury && ttyDisplay->toplin == TOPLINE_NON_EMPTY)
             tty_clear_nhwindow(WIN_MESSAGE);
 
@@ -184,7 +189,7 @@ remember_topl(void)
 void
 addtopl(const char *s)
 {
-    register struct WinDesc *cw = wins[WIN_MESSAGE];
+    struct WinDesc *cw = wins[WIN_MESSAGE];
 
     tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
     putsyms(s);
@@ -220,8 +225,10 @@ more(void)
 
     xwaitforspace("\033 ");
 
-    if (morc == '\033')
-        cw->flags |= WIN_STOP;
+    if (morc == '\033') {
+        if (!(cw->flags & WIN_NOSTOP))
+            cw->flags |= WIN_STOP;
+    }
 
     if (ttyDisplay->toplin && cw->cury) {
         docorner(1, cw->cury + 1);
@@ -243,24 +250,25 @@ update_topl(register const char *bp)
     register int n0;
     int notdied = 1;
     struct WinDesc *cw = wins[WIN_MESSAGE];
+    boolean skip = (cw->flags & (WIN_STOP | WIN_NOSTOP)) == WIN_STOP;
 
     /* If there is room on the line, print message on same line */
     /* But messages like "You die..." deserve their own line */
     n0 = strlen(bp);
-    if ((ttyDisplay->toplin == TOPLINE_NEED_MORE || (cw->flags & WIN_STOP))
+    if ((ttyDisplay->toplin == TOPLINE_NEED_MORE || skip)
         && cw->cury == 0
         && n0 + (int) strlen(g.toplines) + 3 < CO - 8 /* room for --More-- */
         && (notdied = strncmp(bp, "You die", 7)) != 0) {
         Strcat(g.toplines, "  ");
         Strcat(g.toplines, bp);
         cw->curx += 2;
-        if (!(cw->flags & WIN_STOP))
+        if (!skip)
             addtopl(bp);
         return;
-    } else if (!(cw->flags & WIN_STOP)) {
+    } else if (!skip) {
         if (ttyDisplay->toplin == TOPLINE_NEED_MORE) {
             more();
-        } else if (cw->cury) { /* for toplin == TOPLINE_NON_EMPTY && cury > 1 */
+        } else if (cw->cury) { /* for toplin==TOPLINE_NON_EMPTY && cury > 1 */
             docorner(1, cw->cury + 1); /* reset cury = 0 if redraw screen */
             cw->curx = cw->cury = 0;   /* from home--cls() & docorner(1,n) */
         }
@@ -283,9 +291,9 @@ update_topl(register const char *bp)
         *tl++ = '\n';
         n0 = strlen(tl);
     }
-    if (!notdied)
-        cw->flags &= ~WIN_STOP;
-    if (!(cw->flags & WIN_STOP))
+    if (!notdied) /* double negative => "You die"; avoid suppressing mesg */
+        cw->flags &= ~WIN_STOP, skip = FALSE;
+    if (!skip)
         redotoplin(g.toplines);
 }
 
@@ -351,18 +359,19 @@ extern char erase_char; /* from xxxtty.c; don't need kill_char */
 /* returns a single keystroke; also sets 'yn_number' */
 char
 tty_yn_function(const char *query, const char *resp, char def)
-/*
- *   Generic yes/no function. 'def' is the default (returned by space or
- *   return; 'esc' returns 'q', or 'n', or the default, depending on
- *   what's in the string. The 'query' string is printed before the user
- *   is asked about the string.
- *   If resp is NULL, any single character is accepted and returned.
- *   If not-NULL, only characters in it are allowed (exceptions:  the
- *   quitchars are always allowed, and if it contains '#' then digits
- *   are allowed); if it includes an <esc>, anything beyond that won't
- *   be shown in the prompt to the user but will be acceptable as input.
- */
 {
+    /*
+     * Generic yes/no function.  'def' is the default (returned by space
+     * or return; 'esc' returns 'q', or 'n', or the default, depending on
+     * what's in the string.  The 'query' string is printed before the user
+     * is asked about the string.
+     *
+     * If resp is NULL, any single character is accepted and returned.
+     * If not-NULL, only characters in it are allowed (exceptions:  the
+     * quitchars are always allowed, and if it contains '#' then digits
+     * are allowed).  If it includes an <esc>, anything beyond that won't
+     * be shown in the prompt to the user but will be acceptable as input.
+     */
     register char q;
     char rtmp[40];
     boolean digit_ok, allow_num, preserve_case = FALSE;
@@ -371,9 +380,10 @@ tty_yn_function(const char *query, const char *resp, char def)
     char prompt[BUFSZ];
 
     yn_number = 0L;
-    if (ttyDisplay->toplin == TOPLINE_NEED_MORE && !(cw->flags & WIN_STOP))
+    if (ttyDisplay->toplin == TOPLINE_NEED_MORE
+        && (cw->flags & (WIN_STOP | WIN_NOSTOP)) != WIN_STOP)
         more();
-    cw->flags &= ~WIN_STOP;
+    cw->flags &= ~(WIN_STOP | WIN_NOSTOP);
     ttyDisplay->toplin = TOPLINE_SPECIAL_PROMPT;
     ttyDisplay->inread++;
     if (resp) {
index 4f95f7e53e59607561141ea1343f8c20ba60f57a..c0717c62076e7a9d8e85c16f5473a1d411a9b0f7 100644 (file)
@@ -2309,8 +2309,9 @@ process_text_window(winid window, struct WinDesc *cw)
 
 /*ARGSUSED*/
 void
-tty_display_nhwindow(winid window,
-                    boolean blocking) /* with ttys, all windows are blocking */
+tty_display_nhwindow(
+    winid window,
+    boolean blocking) /* with ttys, all windows are blocking */
 {
     register struct WinDesc *cw = 0;
     short s_maxcol;
@@ -2666,9 +2667,17 @@ tty_putstr(winid window, int attr, const char *str)
             urgent_message = (attr & ATR_URGENT);
 
         /* if message is designated 'urgent' don't suppress it if user has
-           typed ESC at --More-- prompt when dismissing an earlier message */
-        if (urgent_message)
-            cw->flags &= ~WIN_STOP;
+           typed ESC at --More-- prompt when dismissing an earlier message;
+           besides turning off WIN_STOP, we need to prevent current message
+           from provoking --More-- and giving the user another chance at
+           using ESC to suppress, otherwise this message wouldn't get shown */
+        if (urgent_message) {
+            if ((cw->flags & WIN_STOP) != 0) {
+                tty_clear_nhwindow(WIN_MESSAGE);
+                cw->flags &= ~WIN_STOP;
+            }
+            cw->flags |= WIN_NOSTOP;
+        }
 
         /* in case we ever support display attributes for topline
            messages, clear flag mask leaving only display attr */
@@ -2684,6 +2693,8 @@ tty_putstr(winid window, int attr, const char *str)
             /* write to top line without remembering what we're writing */
             show_topl(str);
         }
+
+        cw->flags &= ~WIN_NOSTOP; /* NOSTOP is a one-shot operation */
         break;
     }
 #ifndef STATUS_HILITES