From d4f0450afebf6351480c5163040f36fc223206de Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 30 Aug 2022 15:01:49 -0700 Subject: [PATCH] fix the tty message spacing anomaly for messages \ delivered across level change checkpointing Reported by entrez. Simplest test case: give level 1 a short annotatation, level teleport to level 2, and level teleport back to level 1. The message window will show |You materialize on another level. You remember this level as . but ^P message history will show |You materialize on another level. | You remember this level as . Spaces inserted to separate two messages that fit together on the top line become part of the second message when saving a checkpoint during level change flushes the top line into message history. Change insurance checkpointing to record the full message history without flushing the current top line so that toggling 'checkpoint' doesn't affect what shows up on the screen or in message recall. --- include/decl.h | 32 +++++++++++++++++--------------- src/do.c | 2 ++ win/tty/topl.c | 19 ++++++++++++------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/include/decl.h b/include/decl.h index e931fc09b..e5bd58910 100644 --- a/include/decl.h +++ b/include/decl.h @@ -83,34 +83,36 @@ E NEARDATA char tune[6]; #define MAXLINFO (MAXDUNGEON * MAXLEVEL) +/* structure for 'program_state'; not saved and restored */ struct sinfo { - int gameover; /* self explanatory? */ - int stopprint; /* inhibit further end of game disclosure */ + int gameover; /* self explanatory? */ + int stopprint; /* inhibit further end of game disclosure */ #ifdef HANGUPHANDLING - volatile int done_hup; /* SIGHUP or moral equivalent received - * -- no more screen output */ - int preserve_locks; /* don't remove level files prior to exit */ + volatile int done_hup; /* SIGHUP or moral equivalent received + * -- no more screen output */ + int preserve_locks; /* don't remove level files prior to exit */ #endif int something_worth_saving; /* in case of panic */ int panicking; /* `panic' is in progress */ int exiting; /* an exit handler is executing */ - int saving; - int restoring; - int in_moveloop; - int in_impossible; - int in_docrt; /* in docrt() */ - int in_self_recover; + int saving; /* creating a save file */ + int restoring; /* reloading a save file */ + int in_moveloop; /* normal gameplay in progress */ + int in_impossible; /* reportig a warning */ + int in_docrt; /* in docrt(): redrawing the whole screen */ + int in_self_recover; /* processsing orphaned level files */ + int in_checkpoint; /* saving insurance checkpoint */ 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; + int in_paniclog; /* writing a panicloc entry */ #endif - int wizkit_wishing; + int wizkit_wishing; /* starting wizard mode game w/ WIZKIT file */ /* getting_a_command: only used for ALTMETA config to process ESC, but present and updated unconditionally; set by parse() when requesting next command keystroke, reset by readchar() as it returns a key */ - int getting_a_command; + int getting_a_command; /* next key pressed will be entering a cmnd */ }; /* Flags for controlling uptodate */ @@ -854,7 +856,7 @@ struct instance_globals { #ifdef MICRO char levels[PATHLEN]; /* where levels are */ #endif /* MICRO */ - struct sinfo program_state; + struct sinfo program_state; /* flags describing game's current state */ /* detect.c */ diff --git a/src/do.c b/src/do.c index f26ffe68d..479dfbade 100644 --- a/src/do.c +++ b/src/do.c @@ -1248,6 +1248,7 @@ save_currentstate(void) { NHFILE *nhfp; + g.program_state.in_checkpoint++; if (flags.ins_chkpt) { /* write out just-attained level, with pets and everything */ nhfp = currentlevel_rewrite(); @@ -1262,6 +1263,7 @@ save_currentstate(void) /* write out non-level state */ savestateinlock(); + g.program_state.in_checkpoint--; } #endif diff --git a/win/tty/topl.c b/win/tty/topl.c index 69f965e92..f28926406 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -184,8 +184,10 @@ remember_topl(void) cw->datlen[idx] = (short) len; } Strcpy(cw->data[idx], g.toplines); - *g.toplines = '\0'; - cw->maxcol = cw->maxrow = (idx + 1) % cw->rows; + if (!g.program_state.in_checkpoint) { + *g.toplines = '\0'; + cw->maxcol = cw->maxrow = (idx + 1) % cw->rows; + } } void @@ -360,13 +362,16 @@ 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) +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. + * what's in the expected-response 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 @@ -548,8 +553,8 @@ static char **snapshot_mesgs = 0; /* collect currently available message history data into a sequential array; optionally, purge that data from the active circular buffer set as we go */ static void -msghistory_snapshot(boolean purge) /* clear message history buffer - as we copy it */ +msghistory_snapshot( + boolean purge) /* clear message history buffer as we copy it */ { char *mesg; int i, inidx, outidx;