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.
This commit is contained in:
@@ -101,6 +101,7 @@ struct sinfo {
|
|||||||
int in_self_recover;
|
int in_self_recover;
|
||||||
int in_parseoptions; /* in parseoptions */
|
int in_parseoptions; /* in parseoptions */
|
||||||
int config_error_ready; /* config_error_add is ready, available */
|
int config_error_ready; /* config_error_add is ready, available */
|
||||||
|
int beyond_savefile_load; /* set when past savefile loading */
|
||||||
#ifdef PANICLOG
|
#ifdef PANICLOG
|
||||||
int in_paniclog;
|
int in_paniclog;
|
||||||
#endif
|
#endif
|
||||||
@@ -1262,6 +1263,8 @@ struct instance_globals {
|
|||||||
|
|
||||||
/* per-level glyph mapping flags */
|
/* per-level glyph mapping flags */
|
||||||
long glyphmap_perlevel_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 */
|
unsigned long magic; /* validate that structure layout is preserved */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -693,6 +693,7 @@ const struct instance_globals g_init = {
|
|||||||
|
|
||||||
/* per-level glyph mapping flags */
|
/* per-level glyph mapping flags */
|
||||||
0L, /* glyphmap_perlevel_flags */
|
0L, /* glyphmap_perlevel_flags */
|
||||||
|
0, /* early_raw_messages */
|
||||||
|
|
||||||
IVMAGIC /* used to validate that structure layout has been preserved */
|
IVMAGIC /* used to validate that structure layout has been preserved */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -462,6 +462,8 @@ raw_printf(const char *line, ...)
|
|||||||
va_start(the_args, line);
|
va_start(the_args, line);
|
||||||
vraw_printf(line, the_args);
|
vraw_printf(line, the_args);
|
||||||
va_end(the_args);
|
va_end(the_args);
|
||||||
|
if (!g.program_state.beyond_savefile_load)
|
||||||
|
g.early_raw_messages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DISABLE_WARNING_FORMAT_NONLITERAL
|
DISABLE_WARNING_FORMAT_NONLITERAL
|
||||||
@@ -489,6 +491,8 @@ vraw_printf(const char *line, va_list the_args)
|
|||||||
#if defined(MSGHANDLER)
|
#if defined(MSGHANDLER)
|
||||||
execplinehandler(line);
|
execplinehandler(line);
|
||||||
#endif
|
#endif
|
||||||
|
if (!g.program_state.beyond_savefile_load)
|
||||||
|
g.early_raw_messages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -870,6 +870,17 @@ dorecover(NHFILE* nhfp)
|
|||||||
|
|
||||||
run_timers(); /* expire all timers that have gone off while away */
|
run_timers(); /* expire all timers that have gone off while away */
|
||||||
g.program_state.restoring = 0; /* affects bot() so clear before docrt() */
|
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();
|
docrt();
|
||||||
clear_nhwindow(WIN_MESSAGE);
|
clear_nhwindow(WIN_MESSAGE);
|
||||||
|
|
||||||
|
|||||||
@@ -235,7 +235,12 @@ main(int argc, char *argv[])
|
|||||||
iflags.news = FALSE; /* in case dorecover() fails */
|
iflags.news = FALSE; /* in case dorecover() fails */
|
||||||
}
|
}
|
||||||
#endif
|
#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 */
|
mark_synch(); /* flush output */
|
||||||
if (dorecover(nhfp)) {
|
if (dorecover(nhfp)) {
|
||||||
resuming = TRUE; /* not starting new game */
|
resuming = TRUE; /* not starting new game */
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ getlock(void)
|
|||||||
/* this is a candidate for paranoid_confirmation */
|
/* this is a candidate for paranoid_confirmation */
|
||||||
c = yn(destroy_old_game_prompt);
|
c = yn(destroy_old_game_prompt);
|
||||||
} else {
|
} else {
|
||||||
(void) printf("\n%s [yn] ", destroy_old_game_prompt);
|
(void) raw_printf("\n%s [yn] ", destroy_old_game_prompt);
|
||||||
(void) fflush(stdout);
|
(void) fflush(stdout);
|
||||||
if ((c = getchar()) != EOF) {
|
if ((c = getchar()) != EOF) {
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|||||||
@@ -625,7 +625,10 @@ attempt_restore:
|
|||||||
iflags.news = FALSE;
|
iflags.news = FALSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pline("Restoring save file...");
|
if (g.early_raw_messages)
|
||||||
|
raw_print("Restoring save file...");
|
||||||
|
else
|
||||||
|
pline("Restoring save file...");
|
||||||
mark_synch(); /* flush output */
|
mark_synch(); /* flush output */
|
||||||
if (dorecover(nhfp)) {
|
if (dorecover(nhfp)) {
|
||||||
resuming = TRUE; /* not starting new game */
|
resuming = TRUE; /* not starting new game */
|
||||||
@@ -1193,7 +1196,7 @@ getlock(void)
|
|||||||
: "not start a new game");
|
: "not start a new game");
|
||||||
if (istty)
|
if (istty)
|
||||||
clear_screen();
|
clear_screen();
|
||||||
pline(oops);
|
raw_printf("%s", oops);
|
||||||
if (prompt_result == 1) { /* recover */
|
if (prompt_result == 1) { /* recover */
|
||||||
if (recover_savefile()) {
|
if (recover_savefile()) {
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@@ -469,6 +469,7 @@ windows_console_custom_nhgetch(void)
|
|||||||
return _getch();
|
return _getch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int windows_console_custom_nhgetch(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
getreturn(const char *str)
|
getreturn(const char *str)
|
||||||
@@ -481,6 +482,8 @@ getreturn(const char *str)
|
|||||||
in_getreturn = TRUE;
|
in_getreturn = TRUE;
|
||||||
Sprintf(buf,"Hit <Enter> %s.", str);
|
Sprintf(buf,"Hit <Enter> %s.", str);
|
||||||
raw_print(buf);
|
raw_print(buf);
|
||||||
|
if (WINDOWPORT("tty"))
|
||||||
|
windows_console_custom_nhgetch();
|
||||||
wait_synch();
|
wait_synch();
|
||||||
in_getreturn = FALSE;
|
in_getreturn = FALSE;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -115,12 +115,12 @@ struct window_procs tty_procs = {
|
|||||||
| WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
|
| WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
|
||||||
| WC2_RESET_STATUS
|
| WC2_RESET_STATUS
|
||||||
#endif
|
#endif
|
||||||
| WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES)
|
| WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES
|
||||||
| WC2_U_UTF8STR
|
| WC2_U_UTF8STR
|
||||||
#if !defined(NO_TERMS) || defined(WIN32)
|
#if !defined(NO_TERMS) || defined(WIN32)
|
||||||
| WC2_U_24BITCOLOR
|
| WC2_U_24BITCOLOR
|
||||||
#endif
|
#endif
|
||||||
,
|
),
|
||||||
#ifdef TEXTCOLOR
|
#ifdef TEXTCOLOR
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
|
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
|
||||||
#else
|
#else
|
||||||
@@ -481,12 +481,29 @@ tty_init_nhwindows(int *argcp UNUSED, char **argv UNUSED)
|
|||||||
|
|
||||||
tty_clear_nhwindow(BASE_WINDOW);
|
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)
|
for (i = 1; i <= 4; ++i)
|
||||||
tty_putstr(BASE_WINDOW, 0, copyright_banner_line(i));
|
tty_putstr(BASE_WINDOW, 0, copyright_banner_line(i));
|
||||||
tty_putstr(BASE_WINDOW, 0, "");
|
tty_putstr(BASE_WINDOW, 0, "");
|
||||||
tty_display_nhwindow(BASE_WINDOW, FALSE);
|
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;
|
/* 'statuslines' defaults to set_in_config, allowed but invisible;
|
||||||
make it dynamically settable if feasible, otherwise visible */
|
make it dynamically settable if feasible, otherwise visible */
|
||||||
if (tty_procs.wincap2 & WC2_STATUSLINES)
|
if (tty_procs.wincap2 & WC2_STATUSLINES)
|
||||||
|
|||||||
Reference in New Issue
Block a user