diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 64988cf11..4a638b5f0 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.288 $ $NHDT-Date: 1597707740 2020/08/17 23:42:20 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.289 $ $NHDT-Date: 1597967807 2020/08/20 23:56:47 $ General Fixes and Modified Features ----------------------------------- @@ -383,6 +383,12 @@ Qt: "paper doll" subset of persistent inventory has undergone several changes: first active light source in a previously unused slot on lower right; show first leash-in-use in a previously unused slot on lower left Qt: paper doll inventory view was inconsistently updated during Hallucination +Qt: when hero died, gold on tombstone only included gold in inventory, not + any additional gold inside carried containers; also, inventory gold + will be zero if bones get created for all 3.6.x and for 3.4.x+GOLDOBJ +Qt: tombstone showed newly constructed date instead of the value set up at + time of death; it only shows year but that could be wrong if player + stared at or ignored prior --More-- for long enough on 31 December Qt+QSX: fix control key Qt+OSX: rename menu entry "nethack->Preferences..." for invoking nethack's 'O' command to "Game->Run-time options" and entry "Game->Qt settings" diff --git a/include/wincurs.h b/include/wincurs.h index ad7be2083..4e5ce4e78 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -105,7 +105,7 @@ extern void curses_number_pad(int state); extern void curses_delay_output(void); extern void curses_start_screen(void); extern void curses_end_screen(void); -extern void curses_outrip(winid wid, int how); +extern void curses_outrip(winid wid, int how, time_t when); extern void genl_outrip(winid tmpwin, int how, time_t when); extern void curses_preference_update(const char *pref); extern void curs_reset_windows(boolean, boolean); diff --git a/src/rip.c b/src/rip.c index 2996d21a2..dca074720 100644 --- a/src/rip.c +++ b/src/rip.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 rip.c $NHDT-Date: 1596498204 2020/08/03 23:43:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.32 $ */ +/* NetHack 3.7 rip.c $NHDT-Date: 1597967808 2020/08/20 23:56:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.33 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -60,12 +60,10 @@ static const char *rip_txt[] = { }; #define STONE_LINE_CENT 19 /* char[] element of center of stone face */ #endif /* NH320_DEDICATION */ -#define STONE_LINE_LEN \ - 16 /* # chars that fit on one line \ - * (note 1 ' ' border) \ - */ -#define NAME_LINE 6 /* *char[] line # for player name */ -#define GOLD_LINE 7 /* *char[] line # for amount of gold */ +#define STONE_LINE_LEN 16 /* # chars that fit on one line + * (note 1 ' ' border) */ +#define NAME_LINE 6 /* *char[] line # for player name */ +#define GOLD_LINE 7 /* *char[] line # for amount of gold */ #define DEATH_LINE 8 /* *char[] line # for death description */ #define YEAR_LINE 12 /* *char[] line # for year */ @@ -90,9 +88,9 @@ time_t when; register char **dp; register char *dpx; char buf[BUFSZ]; - long year; register int x; - int line; + int line, year; + long cash; g.rip = dp = (char **) alloc(sizeof(rip_txt)); for (x = 0; rip_txt[x]; ++x) @@ -100,13 +98,15 @@ time_t when; dp[x] = (char *) 0; /* Put name on stone */ - Sprintf(buf, "%s", g.plname); - buf[STONE_LINE_LEN] = 0; + Sprintf(buf, "%.*s", (int) STONE_LINE_LEN, g.plname); center(NAME_LINE, buf); /* Put $ on stone */ - Sprintf(buf, "%ld Au", g.done_money); - buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ + cash = max(g.done_money, 0L); + /* arbitrary upper limit; practical upper limit is quite a bit less */ + if (cash > 999999999L) + cash = 999999999L; + Sprintf(buf, "%ld Au", cash); center(GOLD_LINE, buf); /* Put together death description */ @@ -114,11 +114,11 @@ time_t when; /* Put death type on stone */ for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) { - register int i, i0; char tmpchar; + int i, i0 = (int) strlen(dpx); - if ((i0 = strlen(dpx)) > STONE_LINE_LEN) { - for (i = STONE_LINE_LEN; ((i0 > STONE_LINE_LEN) && i); i--) + if (i0 > STONE_LINE_LEN) { + for (i = STONE_LINE_LEN; (i > 0) && (i0 > STONE_LINE_LEN); --i) if (dpx[i] == ' ') i0 = i; if (!i) @@ -135,8 +135,8 @@ time_t when; } /* Put year on stone */ - year = yyyymmdd(when) / 10000L; - Sprintf(buf, "%4ld", year); + year = (int) ((yyyymmdd(when) / 10000L) % 10000L); + Sprintf(buf, "%4d", year); center(YEAR_LINE, buf); #ifdef DUMPLOG diff --git a/win/Qt/qt_menu.cpp b/win/Qt/qt_menu.cpp index b3d192eb1..817449ee7 100644 --- a/win/Qt/qt_menu.cpp +++ b/win/Qt/qt_menu.cpp @@ -653,7 +653,7 @@ bool NetHackQtTextWindow::Destroy() return !isVisible(); } -void NetHackQtTextWindow::UseRIP(int how, time_t when UNUSED) +void NetHackQtTextWindow::UseRIP(int how, time_t when) { // Code from X11 windowport #define STONE_LINE_LEN 16 /* # chars that fit on one line */ @@ -677,41 +677,63 @@ static char** rip_line=0; int line; /* Put name on stone */ - snprintf(rip_line[NAME_LINE], STONE_LINE_LEN+1, "%s", g.plname); + (void) snprintf(rip_line[NAME_LINE], STONE_LINE_LEN + 1, + "%.*s", STONE_LINE_LEN, g.plname); - /* Put $ on stone */ - snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN+1, "%ld Au", money_cnt(g.invent)); + /* Put $ on stone; + to keep things safe and relatively simple, impose an arbitrary + upper limit that's the same for 64 bit and 32 bit configurations + (also 16 bit configurations provided they use 32 bit long); the + upper limit for directly carried gold is somewhat less than 300K + due to carrying capacity, but end-of-game handling has already + added in gold from containers, so the amount could be much more + (simplest case: ~300K four times in a blessed bag of holding, so + ~1.2M; in addition to the hassle of getting such a thing set up, + it would need many gold-rich bones levels or wizard mode wishing) */ + long cash = std::max(g.done_money, 0L); + /* force less that 10 digits to satisfy elaborate format checking; + it's arbitrary but still way, way more than could ever be needed */ + if (cash > 999999999L) + cash = 999999999L; + (void) snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN + 1, "%ld Au", cash); /* Put together death description */ formatkiller(buf, sizeof buf, how, FALSE); //str_copy(buf, killer, SIZE(buf)); /* Put death type on stone */ - for (line=DEATH_LINE, dpx = buf; line STONE_LINE_LEN) { - for(i = STONE_LINE_LEN; - ((i0 > STONE_LINE_LEN) && i); i--) - if(dpx[i] == ' ') i0 = i; - if(!i) i0 = STONE_LINE_LEN; + if (i0 > STONE_LINE_LEN) { + for (i = STONE_LINE_LEN; (i > 0) && (i0 > STONE_LINE_LEN); --i) + if (dpx[i] == ' ') + i0 = i; + if (!i) + i0 = STONE_LINE_LEN; } tmpchar = dpx[i0]; dpx[i0] = 0; - str_copy(rip_line[line], dpx, STONE_LINE_LEN+1); + (void) str_copy(rip_line[line], dpx, STONE_LINE_LEN + 1); if (tmpchar != ' ') { dpx[i0] = tmpchar; dpx= &dpx[i0]; - } else dpx= &dpx[i0+1]; + } else { + dpx= &dpx[i0 + 1]; + } } - /* Put year on stone */ - snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN+1, "%4d", getyear()); + /* Put year on stone; + 64 bit configuration with 64 bit int is capable of overflowing + STONE_LINE_LEN characters; a compiler might warn about that, + so force a value that it can recognize as fitting within buffer's + range ("%4d" imposes a minimum number of digits, not a maximum) */ + int year = (int) ((yyyymmdd(when) / 10000L) % 10000L); /* Y10K bug! */ + (void) snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN + 1, "%4d", year); - rip.setLines(rip_line,YEAR_LINE+1); - - use_rip=true; + rip.setLines(rip_line, YEAR_LINE + 1); + use_rip = true; } void NetHackQtTextWindow::Clear() @@ -820,8 +842,9 @@ void NetHackQtMenuOrTextWindow::StartMenu() if (!actual) actual=new NetHackQtMenuWindow(parent); actual->StartMenu(); } -void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr, - const QString& str, unsigned itemflags) +void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, + char ch, char gch, int attr, + const QString& str, unsigned itemflags) { if (!actual) impossible("AddMenu called before we know if Menu or Text"); actual->AddMenu(glyph,identifier,ch,gch,attr,str,itemflags); diff --git a/win/X11/wintext.c b/win/X11/wintext.c index 2a8f19315..a6c2737b8 100644 --- a/win/X11/wintext.c +++ b/win/X11/wintext.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 wintext.c $NHDT-Date: 1596498376 2020/08/03 23:46:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.21 $ */ +/* NetHack 3.7 wintext.c $NHDT-Date: 1597967808 2020/08/20 23:56:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.22 $ */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -489,14 +489,20 @@ calculate_rip_text(int how, time_t when) char buf[BUFSZ]; char *dpx; - int line; - long year; + int line, year; + long cash; /* Put name on stone */ Sprintf(rip_line[NAME_LINE], "%s", g.plname); /* Put $ on stone */ - Sprintf(rip_line[GOLD_LINE], "%ld Au", g.done_money); + cash = max(g.done_money, 0L); + /* arbitrary upper limit; practical upper limit is quite a bit less */ + if (cash > 999999999L) + cash = 999999999L; + Sprintf(buf, "%ld Au", cash); + Sprintf(rip_line[GOLD_LINE], "%ld Au", cash); + /* Put together death description */ formatkiller(buf, sizeof buf, how, FALSE); @@ -523,8 +529,8 @@ calculate_rip_text(int how, time_t when) } /* Put year on stone */ - year = yyyymmdd(when) / 10000L; - Sprintf(rip_line[YEAR_LINE], "%4ld", year); + year = (int) ((yyyymmdd(when) / 10000L) % 10000L); + Sprintf(rip_line[YEAR_LINE], "%4d", year); } /* diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index e098e163a..4035b3c9f 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -898,12 +898,13 @@ curses_end_screen() /* outrip(winid, int) - -- The tombstone code. If you want the traditional code use - genl_outrip for the value and check the #if in rip.c. + -- The tombstone code. We use genl_outrip() from rip.c + instead of rolling our own. */ void curses_outrip(winid wid UNUSED, - int how UNUSED) + int how UNUSED, + time_t when UNUSED) { return; }