From: nhmall Date: Thu, 9 Jun 2022 03:41:45 +0000 (-0400) Subject: Re: [NetHack/NetHack] Prompts can overwrite copyright notice on the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2e3c1f8de96d72bad7c8dcdc288599c0b5c9f11;p=nethack Re: [NetHack/NetHack] Prompts can overwrite copyright notice on the starting screen (Issue #783) On 2022-06-01 12:22 p.m., NetSysFire wrote: > Steps to reproduce: > >1. Get any prompt and answer it. In my case it was a horribly old > save I forgot about or when I wiztested something and forgot > about that save, too. >2. See that the copyright information got overwritten by the prompt: > >There is already a game in progress under your name. Destroy old game? [yn] (n) > By Stichting Mathematisch Centrum and M. Stephenson. > Version 3.7.0-59 Unix Work-in-progress, built May 31 2022 12:28:31. > See license for details. > > > Shall I pick character's race, role, gender and alignment for you? [ynaq] > > Expected behavior: > > Redraw after a prompt was answered, so the prompt vanishes and the > entirety of the starting screen will be shown. > > NetHack, Copyright 1985-2022 > By Stichting Mathematisch Centrum and M. Stephenson. > Version 3.7.0-59 Unix Work-in-progress, built May 31 2022 12:28:31. > See license for details. > > > Shall I pick character's race, role, gender and alignment for you? [ynaq] > > Proposed severity: low. Not gamebreaking, it is cosmetic only and does > not have any other consequences. > The Copyright notice is placed by tty internal routines writing onto the BASE_WINDOW fairly early in the startup sequence. The prompt to "Destroy old game? [yn] (n)" is using the in-game routine to write to the message window at the top of the screen and prompt there, just like in-game prompts and messages. If the player answered 'y' to that, the prompt for "Shall I pick character's race, role, gender and alignment..." appeared immediately after. That one, however, is written using the BASE_WINDOW routines in tty, like the copyright notice. This change does the following: It moves the copyright lines down a little bit leaving room for the "Destroy.." prompts. It places the "Shall I pick characters's..." prompt further down the screen by default, leaving some room for about 3 raw_print startup messages after the copyright notice, just in case there are any. The "Shall I pick character's..." prompt will still appear immediately if there is a prompt such as "Destroy old game?..." There were a couple of other issues around raw_print startup messages too. Those are delivered using a raw_print mechanism to ensure they are written even if the window-port is not fully operational. However, they were only on the screen for the blink of an eye. This call sequence in restore.c made them disappear almost immediately: docrt() -> cls() Put in a mechanism to detect the presence of raw_print messages from the early startup, and if there were some, wait for a keypress before obliterating the unread notifications. --- diff --git a/include/decl.h b/include/decl.h index 662821287..642989027 100644 --- a/include/decl.h +++ b/include/decl.h @@ -101,6 +101,7 @@ struct sinfo { int in_self_recover; int in_parseoptions; /* in parseoptions */ int config_error_ready; /* config_error_add is ready, available */ + int beyond_savefile_load; /* set when past savefile loading */ #ifdef PANICLOG int in_paniclog; #endif @@ -1262,6 +1263,8 @@ struct instance_globals { /* per-level glyph mapping flags */ long glyphmap_perlevel_flags; + int early_raw_messages; /* if raw_prints occurred early prior + to g.beyond_savefile_load */ unsigned long magic; /* validate that structure layout is preserved */ }; diff --git a/src/decl.c b/src/decl.c index 5cf81733a..a38095876 100644 --- a/src/decl.c +++ b/src/decl.c @@ -693,6 +693,7 @@ const struct instance_globals g_init = { /* per-level glyph mapping flags */ 0L, /* glyphmap_perlevel_flags */ + 0, /* early_raw_messages */ IVMAGIC /* used to validate that structure layout has been preserved */ }; diff --git a/src/pline.c b/src/pline.c index 3fac368d8..24dcc49a8 100644 --- a/src/pline.c +++ b/src/pline.c @@ -462,6 +462,8 @@ raw_printf(const char *line, ...) va_start(the_args, line); vraw_printf(line, the_args); va_end(the_args); + if (!g.program_state.beyond_savefile_load) + g.early_raw_messages++; } DISABLE_WARNING_FORMAT_NONLITERAL @@ -489,6 +491,8 @@ vraw_printf(const char *line, va_list the_args) #if defined(MSGHANDLER) execplinehandler(line); #endif + if (!g.program_state.beyond_savefile_load) + g.early_raw_messages++; } void diff --git a/src/restore.c b/src/restore.c index 51d068656..31d07b141 100644 --- a/src/restore.c +++ b/src/restore.c @@ -870,6 +870,17 @@ dorecover(NHFILE* nhfp) run_timers(); /* expire all timers that have gone off while away */ g.program_state.restoring = 0; /* affects bot() so clear before docrt() */ + + if (g.early_raw_messages && !g.program_state.beyond_savefile_load) { + /* + * We're about to obliterate some potentially important + * startup messages, so give the player a chance to see them. + */ + g.early_raw_messages = 0; + wait_synch(); + } + g.program_state.beyond_savefile_load = 0; + docrt(); clear_nhwindow(WIN_MESSAGE); diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 53fe67df1..6f9dc42e0 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -235,7 +235,12 @@ main(int argc, char *argv[]) iflags.news = FALSE; /* in case dorecover() fails */ } #endif - pline("Restoring save file..."); + /* if there are early trouble-messages issued, let's + * not go overtop of them with a pline just yet */ + if (g.early_raw_messages) + raw_print("Restoring save file..."); + else + pline("Restoring save file..."); mark_synch(); /* flush output */ if (dorecover(nhfp)) { resuming = TRUE; /* not starting new game */ diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index cd8a7daa8..c44da845b 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -171,7 +171,7 @@ getlock(void) /* this is a candidate for paranoid_confirmation */ c = yn(destroy_old_game_prompt); } else { - (void) printf("\n%s [yn] ", destroy_old_game_prompt); + (void) raw_printf("\n%s [yn] ", destroy_old_game_prompt); (void) fflush(stdout); if ((c = getchar()) != EOF) { int tmp; diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index ec0ca58c1..f67826287 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -625,7 +625,10 @@ attempt_restore: iflags.news = FALSE; } #endif - pline("Restoring save file..."); + if (g.early_raw_messages) + raw_print("Restoring save file..."); + else + pline("Restoring save file..."); mark_synch(); /* flush output */ if (dorecover(nhfp)) { resuming = TRUE; /* not starting new game */ @@ -1193,7 +1196,7 @@ getlock(void) : "not start a new game"); if (istty) clear_screen(); - pline(oops); + raw_printf("%s", oops); if (prompt_result == 1) { /* recover */ if (recover_savefile()) { #if 0 diff --git a/sys/windows/windsys.c b/sys/windows/windsys.c index b6185801a..78125da75 100644 --- a/sys/windows/windsys.c +++ b/sys/windows/windsys.c @@ -469,6 +469,7 @@ windows_console_custom_nhgetch(void) return _getch(); } +extern int windows_console_custom_nhgetch(void); void getreturn(const char *str) @@ -481,6 +482,8 @@ getreturn(const char *str) in_getreturn = TRUE; Sprintf(buf,"Hit %s.", str); raw_print(buf); + if (WINDOWPORT("tty")) + windows_console_custom_nhgetch(); wait_synch(); in_getreturn = FALSE; return; diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 89ad67f1b..f7c22458e 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -115,12 +115,12 @@ struct window_procs tty_procs = { | WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_RESET_STATUS #endif - | WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES) + | WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES | WC2_U_UTF8STR #if !defined(NO_TERMS) || defined(WIN32) | WC2_U_24BITCOLOR #endif - , + ), #ifdef TEXTCOLOR {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ #else @@ -481,12 +481,29 @@ tty_init_nhwindows(int *argcp UNUSED, char **argv UNUSED) tty_clear_nhwindow(BASE_WINDOW); - tty_putstr(BASE_WINDOW, 0, ""); + /* Once pline() is functional, error-related prompts such as + * those relating to save files etc. can intrude on the + * copyright information display because their prompts are + * up at the very top in the message window. + * Move the copyright information a little further down to + * row 3, out of the way. */ + + tty_curs(BASE_WINDOW, 1, 4); for (i = 1; i <= 4; ++i) tty_putstr(BASE_WINDOW, 0, copyright_banner_line(i)); tty_putstr(BASE_WINDOW, 0, ""); tty_display_nhwindow(BASE_WINDOW, FALSE); + /* Move to a default location for the "Shall I pick .." player + * selection prompts, which also use the BASE_WINDOW. Leave + * room for as many as 3 unexpected raw_prints early startup + * messages above that. + * If there is a topline message prompt, before the + * "Shall I pick ..." prompt, the latter will end up appearing + * immediately after the topline message prompt. There should + * now be room. */ + tty_curs(BASE_WINDOW, 1, 11); + /* 'statuslines' defaults to set_in_config, allowed but invisible; make it dynamically settable if feasible, otherwise visible */ if (tty_procs.wincap2 & WC2_STATUSLINES)