From: nethack.allison Date: Sun, 5 Oct 2003 13:43:16 +0000 (+0000) Subject: saving message history (trunk only) X-Git-Tag: MOVE2GIT~1731 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6f6c1f0d5793b4d75d543fca8a5784a003c6a3f;p=nethack saving message history (trunk only) On September 11, 2003 "" wrote: > When we're going to have a different save file format, could > the last messages in the message history be saved as well, so > ^P would work the same before and after saving (possibly > including a few less messages to make room for the startup > messages?). This seemed like a reasonable request. This patch: - adds the core support required. - adds the tty supporting routines. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index d40f22ec0..0d89421d8 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -59,12 +59,14 @@ burying a punishment ball no longer ends your punishment add clicklook option to allow looking at things on the display by clicking right mouse button when floating mouse pointer over them Izchak's lighting store is now able to stock oil for your lamp +provide core support for saving of messsage history in save file Platform- and/or Interface-Specific New Features ------------------------------------------------ win32gui: support perm_invent win32gui: menu option to add/remove windows captions +tty: add window port routines for saving/restoring message recall history Code Cleanup and Reorganization diff --git a/doc/window.doc b/doc/window.doc index 2c79965ad..126c58e2c 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -378,6 +378,35 @@ preference_update(preference) change if it indicated that it wants to be by setting the corresponding bit in the wincap mask. +getmsghistory(init) + -- This is used to preserve message history between games by + obtaining the messages from the window port so that the core + can put them into the savefile. + The routine is called repeatedly from the core save routine, + and the window port routine is expected to successively return + each message that it wants the game to store in the savefile, + starting with the oldest message first, finishing + with the most recent. + If init is TRUE, start over again from most recent message. + +putmsghistory(msg) + -- The is the counterpart to getmsghistory() for restores + used to reload the port's message recall buffer. + The routine is called repeatedly from the core restore + routine, starting with the oldest message first, and + finishing with the most recent one that it read from the savefile. + The window port routine is expected to load the message + recall buffers in such a way that the ordering remains correct. + The window port routine should make no assumptions about how + many messages are forthcoming, nor should it assume that + another message will follow this one, so it must be careful + to keep all pointers/indexes intact at the end of each call. + If the window port receives more messages that can fit in + its buffers, it is expected to scroll away the oldest from + its buffers, much like it would with new messages being + produced. + + III. Global variables The following global variables are defined in decl.c and must be used by diff --git a/include/extern.h b/include/extern.h index eb0ffb668..b628d1d41 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2288,6 +2288,8 @@ E void FDECL(setmnotwielded, (struct monst *,struct obj *)); E void FDECL(choose_windows, (const char *)); E char FDECL(genl_message_menu, (CHAR_P,int,const char *)); E void FDECL(genl_preference_update, (const char *)); +E char *FDECL(genl_getmsghistory, (BOOLEAN_P)); +E void FDECL(genl_putmsghistory, (const char *)); /* ### wizard.c ### */ diff --git a/include/patchlevel.h b/include/patchlevel.h index aedbd2975..53f883f08 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -13,7 +13,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 3 +#define EDITLEVEL 4 #define COPYRIGHT_BANNER_A \ "NetHack, Copyright 1985-2003" diff --git a/include/winprocs.h b/include/winprocs.h index 2e1f2e995..c1a7eca79 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -65,6 +65,8 @@ struct window_procs { void FDECL((*win_outrip), (winid,int)); void FDECL((*win_preference_update), (const char *)); + char * FDECL((*win_getmsghistory), (BOOLEAN_P)); + void FDECL((*win_putmsghistory), (const char *)); }; extern NEARDATA struct window_procs windowprocs; @@ -134,6 +136,8 @@ extern NEARDATA struct window_procs windowprocs; #define outrip (*windowprocs.win_outrip) #define preference_update (*windowprocs.win_preference_update) +#define getmsghistory (*windowprocs.win_getmsghistory) +#define putmsghistory (*windowprocs.win_putmsghistory) /* * WINCAP diff --git a/include/wintty.h b/include/wintty.h index fc123d89f..3ab8eb449 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -222,6 +222,10 @@ E void NDECL(tty_end_screen); E void FDECL(genl_outrip, (winid,int)); +E char *FDECL(tty_getmsghistory, (BOOLEAN_P)); +E void FDECL(tty_putmsghistory, (const char *)); + + #ifdef NO_TERMS # ifdef MAC # ifdef putchar diff --git a/src/restore.c b/src/restore.c index 369212646..861c40c07 100644 --- a/src/restore.c +++ b/src/restore.c @@ -452,6 +452,7 @@ unsigned int *stuckid, *steedid; /* STEED */ restnames(fd); restore_waterlevel(fd); + restore_msghistory(fd); /* must come after all mons & objs are restored */ relink_timers(FALSE); relink_light_sources(FALSE); @@ -910,6 +911,26 @@ boolean ghostly; clear_id_mapping(); } +restore_msghistory(fd) +register int fd; +{ + int msgsize, k, msgcount = 0; + char msg[BUFSZ]; + + while(1) { + mread(fd, (genericptr_t) &msgsize, sizeof(msgsize)); + if(msgsize == -1) break; + if (msgsize > (BUFSZ - 1)) + panic("restore_msghistory: msg too big (%d)", msgsize); + mread(fd, (genericptr_t)msg, msgsize); + msg[msgsize] = '\0'; + putmsghistory(msg); + ++msgcount; + } +#ifdef DEBUG_MSGCOUNT + pline("Read %d messages from savefile.", msgcount); +#endif +} /* Clear all structures for object and monster ID mapping. */ STATIC_OVL void diff --git a/src/save.c b/src/save.c index 98db2a25e..15a7f21e5 100644 --- a/src/save.c +++ b/src/save.c @@ -339,6 +339,7 @@ register int fd, mode; savefruitchn(fd, mode); savenames(fd, mode); save_waterlevel(fd, mode); + save_msghistory(fd, mode); bflush(fd); } @@ -984,6 +985,36 @@ register int fd, mode; ffruit = 0; } +save_msghistory(fd, mode) +register int fd, mode; +{ + char *msg, buf[BUFSZ]; + int msgcount = 0, msglen = 0; + int minusone = -1; + boolean init = TRUE; + + /* Ask window port for each message in sequence */ + while ((msg = getmsghistory(init)) != 0) { + init = FALSE; + msglen = strlen(msg); + if (msglen < (BUFSZ-1)) + Strcpy(buf, msg); + else { + /* impossible */ + (void)strncpy(buf, msg, (BUFSZ - 1)); + buf[BUFSZ-1] = '\0'; + msglen = strlen(buf); + } + bwrite(fd, (genericptr_t)&msglen, sizeof(msglen)); + bwrite(fd, (genericptr_t)msg, msglen); + ++msgcount; + } + bwrite(fd, (genericptr_t) &minusone, sizeof(int)); +#ifdef DEBUG_MSGCOUNT + pline("Stored %d messages into savefile.", msgcount); +#endif +} + /* also called by prscore(); this probably belongs in dungeon.c... */ void free_dungeons() diff --git a/src/windows.c b/src/windows.c index 3c590802e..1587ba03e 100644 --- a/src/windows.c +++ b/src/windows.c @@ -143,4 +143,47 @@ const char *pref; they support. Just return in this genl one. */ } + +char * +genl_getmsghistory(init) +boolean init; +{ + /* window ports can provide + their own getmsghistory() routine to + preserve message history between games. + The routine is called repeatedly from + the core save routine, and the window + port is expected to successively return + each message that it wants saved, starting + with the oldest message first, finishing + with the most recent. + Return null pointer when finished. + */ + return (char *)0; +} + +/*ARGSUSED*/ +void +genl_putmsghistory(msg) +const char *msg; +{ + /* window ports can provide + their own putmsghistory() routine to + load message history from a saved game. + The routine is called repeatedly from + the core restore routine, starting with + the oldest saved message first, and + finishing with the latest. + The window port routine is expected to + load the message recall buffers in such + a way that the ordering is preserved. + The window port routine should make no + assumptions about how many messages are + forthcoming, nor should it assume that + another message will follow this one, + so it should keep all pointers/indexes + intact at the end of each call. + */ +} + /*windows.c*/ diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c index 7071bfb70..91f656b39 100644 --- a/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -79,7 +79,9 @@ struct window_procs amii_procs = amii_delay_output, amii_delay_output, amii_outrip, - genl_preference_update + genl_preference_update, + genl_getmsghistory, + genl_putmsghistory }; /* The view window layout uses the same function names so we can use @@ -138,7 +140,9 @@ struct window_procs amiv_procs = amii_delay_output, amii_delay_output, amii_outrip, - genl_preference_update + genl_preference_update, + genl_getmsghistory, + genl_putmsghistory }; unsigned short amii_initmap[ AMII_MAXCOLORS ]; diff --git a/sys/mac/macwin.c b/sys/mac/macwin.c index 8b2f62bc4..e40a21f78 100644 --- a/sys/mac/macwin.c +++ b/sys/mac/macwin.c @@ -2645,6 +2645,8 @@ struct window_procs mac_procs = { 0, // mac_end_screen, genl_outrip, genl_preference_update, + genl_getmsghistory, + genl_putmsghistory, }; /*macwin.c*/ diff --git a/sys/wince/mswproc.c b/sys/wince/mswproc.c index d08e081d0..53a0f9e71 100644 --- a/sys/wince/mswproc.c +++ b/sys/wince/mswproc.c @@ -95,6 +95,8 @@ struct window_procs mswin_procs = { mswin_end_screen, mswin_outrip, mswin_preference_update, + genl_getmsghistory, + genl_putmsghistory, }; /* diff --git a/win/Qt/qt_win.cpp b/win/Qt/qt_win.cpp index 89af564f5..0ae27ae60 100644 --- a/win/Qt/qt_win.cpp +++ b/win/Qt/qt_win.cpp @@ -5285,6 +5285,8 @@ struct window_procs Qt_procs = { genl_outrip, #endif genl_preference_update, + genl_getmsghistory, + genl_putmsghistory, }; extern "C" void play_usersound(const char* filename, int volume) diff --git a/win/X11/winX.c b/win/X11/winX.c index 2dfe116c7..0401f3770 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -157,6 +157,8 @@ struct window_procs X11_procs = { genl_outrip, #endif X11_preference_update, + genl_getmsghistory, + genl_putmsghistory, }; /* diff --git a/win/gem/wingem.c b/win/gem/wingem.c index 2a5ab6529..d5afcb562 100644 --- a/win/gem/wingem.c +++ b/win/gem/wingem.c @@ -97,7 +97,9 @@ struct window_procs Gem_procs = { Gem_start_screen, Gem_end_screen, Gem_outrip, - Gem_preference_update + Gem_preference_update, + genl_getmsghistory, + genl_putmsghistory }; #ifdef MAC diff --git a/win/gnome/gnbind.c b/win/gnome/gnbind.c index c3a8f98a0..b5f4b5031 100644 --- a/win/gnome/gnbind.c +++ b/win/gnome/gnbind.c @@ -73,6 +73,8 @@ struct window_procs Gnome_procs = { gnome_end_screen, gnome_outrip, genl_preference_update, + genl_getmsghistory, + genl_putmsghistory, }; /* diff --git a/win/tty/topl.c b/win/tty/topl.c index da4d39d0a..47707324f 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)topl.c 3.4 1996/10/24 */ +/* SCCS Id: @(#)topl.c 3.4 2003/10/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -443,6 +443,73 @@ char def; return q; } + +/* + * This is called by the core save routines. + * Each time we are called, we return one string from the + * message history starting with the oldest message first. each time + * we are called. Each time after that, we return a more recent message, + * until there are no more messages to return. Then we return a final + * null string. + */ +char * +tty_getmsghistory(init) +boolean init; +{ + static int idx = 0, state = 0; + static boolean doneinit = FALSE; + register struct WinDesc *cw = wins[WIN_MESSAGE]; + char *retstr = (char *)0; + + /* + * state 0 = normal return with string from msg history. + * state 1 = finished with recall data, return toplines. + * state 2 = completely finished, return null string. + */ + if (init) { + doneinit = TRUE; + state = 0; + idx = cw->maxrow; + } + if (doneinit && state < 2) { + if (state == 1) { + ++state; + return toplines; + } + do { + if(cw->data[idx] && strcmp(cw->data[idx], "") ) + retstr = cw->data[idx]; + idx = (idx + 1) % cw->rows; + } while (idx != cw->maxrow && !retstr); + if (idx == cw->maxrow) ++state; + } + return retstr; +} + +/* + * This is called by the core savefile restore routines. + * Each time we are called, we stuff the string into our message + * history recall buffer. The core will send the oldest message + * first (actually it sends them in the order they exist in the + * save file, but that is supposed to be the oldest first). + */ +void +tty_putmsghistory(msg) +const char *msg; +{ + register struct WinDesc *cw = wins[WIN_MESSAGE]; + int idx = cw->maxrow; + unsigned len = strlen(msg) + 1; + + if (len > (unsigned)cw->datlen[idx]) { + if (cw->data[idx]) free(cw->data[idx]); + len += (8 - (len & 7)); /* pad up to next multiple of 8 */ + cw->data[idx] = (char *)alloc(len); + cw->datlen[idx] = (short)len; + } + Strcpy(cw->data[idx], msg); + cw->maxcol = cw->maxrow = (idx + 1) % cw->rows; +} #endif /* TTY_GRAPHICS */ /*topl.c*/ diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 9a0911770..eafff116d 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -109,6 +109,8 @@ struct window_procs tty_procs = { #else genl_preference_update, #endif + tty_getmsghistory, + tty_putmsghistory, }; static int maxwin = 0; /* number of windows in use */ diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index c0a8be40c..2d2448bf6 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -121,6 +121,8 @@ struct window_procs mswin_procs = { mswin_end_screen, mswin_outrip, mswin_preference_update, + genl_getmsghistory, + genl_putmsghistory, };