]> granicus.if.org Git - nethack/commitdiff
saving message history (trunk only)
authornethack.allison <nethack.allison>
Sun, 5 Oct 2003 13:43:16 +0000 (13:43 +0000)
committernethack.allison <nethack.allison>
Sun, 5 Oct 2003 13:43:16 +0000 (13:43 +0000)
On September 11, 2003 "<Someone>" 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.

19 files changed:
doc/fixes35.0
doc/window.doc
include/extern.h
include/patchlevel.h
include/winprocs.h
include/wintty.h
src/restore.c
src/save.c
src/windows.c
sys/amiga/winami.c
sys/mac/macwin.c
sys/wince/mswproc.c
win/Qt/qt_win.cpp
win/X11/winX.c
win/gem/wingem.c
win/gnome/gnbind.c
win/tty/topl.c
win/tty/wintty.c
win/win32/mswproc.c

index d40f22ec0380211eb66bc8c449bdbbc42be5aee4..0d89421d83206792e99e423e656a6ae31adf25ba 100644 (file)
@@ -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
index 2c79965ad699eb6c98c9ccf02ab389e481e48190..126c58e2ca1fa1a8be7c3777b9f5aae9a33eaa09 100644 (file)
@@ -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
index eb0ffb668f9ee4b44ad3a472dd4afbcca5ab6afb..b628d1d41c47b6870e5b4669490f1b762765a101 100644 (file)
@@ -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 ### */
 
index aedbd297537e198f3aba5b910d209175b8618e33..53f883f0881f7b7424e3234c78fd9391ecaf1b62 100644 (file)
@@ -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"
index 2e1f2e995ceda4e7283692cbf7208d97fe5022a2..c1a7eca7992d4f436be09c7345214649d4fb1708 100644 (file)
@@ -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
index fc123d89f769e51122e7171d7fd050879e640c08..3ab8eb4499790cef12d56dc5c4e404dd6ef0a24f 100644 (file)
@@ -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
index 3692126464ff130707de26bf517aa31d6f27304e..861c40c07b9be4f6d28b361853dc9d0bcfec3fb2 100644 (file)
@@ -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
index 98db2a25e3e0c2989abee6335f796d706b47088f..15a7f21e5a15667d315f6ced9ebaeade607f342f 100644 (file)
@@ -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()
index 3c590802ea380214adce29a03609562ff60a6a8e..1587ba03eaeda60c0ffb89f3a0bcc1541dd68b71 100644 (file)
@@ -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*/
index 7071bfb70e7273c3baf29ec97c1e51c5089a85a7..91f656b392746ffdd17ebe496260cf7b9f3bacde 100644 (file)
@@ -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 ];
index 8b2f62bc495cd11ea91b5409de446c85770efea5..e40a21f787fce1db9dcf72d7b752f6cbe0d340fd 100644 (file)
@@ -2645,6 +2645,8 @@ struct window_procs mac_procs = {
        0, //    mac_end_screen,
        genl_outrip,
        genl_preference_update,
+       genl_getmsghistory,
+       genl_putmsghistory,
 };
 
 /*macwin.c*/
index d08e081d04c964987f7cdf9db23d21f268470559..53a0f9e7139ee4c9e8fa4f3843070f3167b1c8fa 100644 (file)
@@ -95,6 +95,8 @@ struct window_procs mswin_procs = {
     mswin_end_screen,
     mswin_outrip,
     mswin_preference_update,
+    genl_getmsghistory,
+    genl_putmsghistory,
 };
 
 /*  
index 89af564f5f5f8e87c40b8068256220d16e6d1427..0ae27ae60af59247ae7bc991c52ce7caa60d3bff 100644 (file)
@@ -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)
index 2dfe116c7ef602ab317069f5739b92953bec8fb2..0401f37704f4ee988b67548aec183c2451a3baec 100644 (file)
@@ -157,6 +157,8 @@ struct window_procs X11_procs = {
     genl_outrip,
 #endif
     X11_preference_update,
+    genl_getmsghistory,
+    genl_putmsghistory,
 };
 
 /*
index 2a5ab652930ac9e57a3283417b57c5e7049e3cd0..d5afcb562509e7ff49aa5c460c1cea25040d012d 100644 (file)
@@ -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
index c3a8f98a0817ad2e35ae6533581af7fb797300c8..b5f4b50317d6dda3e3c6762a3c0627a993e23ac9 100644 (file)
@@ -73,6 +73,8 @@ struct window_procs Gnome_procs = {
     gnome_end_screen,
     gnome_outrip,
     genl_preference_update,
+    genl_getmsghistory,
+    genl_putmsghistory,
 };
 
 /*  
index da4d39d0af0cbb8f028b355d6c6fa67fb22df60f..47707324fe9a5dfbf8ed44010e0b66b360bb7bdd 100644 (file)
@@ -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*/
index 9a09117704724d35f23650d89987a51908bdbbf7..eafff116d7caafd49e187db3cd6fff75b8944cae 100644 (file)
@@ -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 */
index c0a8be40c99a1eaa38a713abf95f0cd03556d1f2..2d2448bf6aef1b8a5b27bccfc6df25394012a5bf 100644 (file)
@@ -121,6 +121,8 @@ struct window_procs mswin_procs = {
     mswin_end_screen,
     mswin_outrip,
     mswin_preference_update,
+    genl_getmsghistory,
+    genl_putmsghistory,
 };