]> granicus.if.org Git - nethack/commitdiff
selectsaved option (trunk only)
authornethack.allison <nethack.allison>
Sun, 9 Jan 2005 21:40:24 +0000 (21:40 +0000)
committernethack.allison <nethack.allison>
Sun, 9 Jan 2005 21:40:24 +0000 (21:40 +0000)
- always write plname into save file, no longer conditional
- add 'selectsaved' wincap option to control the display of
  a menu of save files for ports/platforms that support it.
- add support for win32 tty using normal nethack menus.
- the win/tty/wintty code is generalized enough that any
  tty port could support the option if the appropriate port-specific
  code hooks for wildcard file lookups are added to src/file.c
  specifically in the get_saved_games() routine. There is posix
  code in there from Warwick already, and there is findfirst/findnext
  code in there from win32. Warwick has the posix code only
  enabled for Qt at present, but with wintty support, that could be expanded
  to other Unix environments quite easily I would think.

Here is what the tty support looks like:

    NetHack, Copyright 1985-2005
         By Stichting Mathematisch Centrum and M. Stephenson.
         See license for details.

    Select one of your saved games
    a - Bob
    b - Fred
    c - June
    d - mine3
    e - Sirius
    f - Start a new character
    (end)

The following files existed in the NetHack SAVEDIR directory
at the time:
    ALLISONMI-Bob.NetHack-saved-game
    ALLISONMI-Fred.NetHack-saved-game
    ALLISONMI-June.NetHack-saved-game
    ALLISONMI-mine3.NetHack-saved-game
    ALLISONMI-Sirius.NetHack-saved-game
Note that despite the file names, the actual character name
is drawn from the savefile.

The WIN32CON support passes
    USER-*.NetHack-saved-game
to findfirst/findnext where USER is your login name of course.

14 files changed:
doc/Guidebook.mn
doc/Guidebook.tex
doc/fixes35.0
doc/window.doc
include/extern.h
include/flag.h
include/ntconf.h
include/patchlevel.h
include/winprocs.h
src/files.c
src/options.c
src/restore.c
src/save.c
win/tty/wintty.c

index d1a05d564cd583bf50270acc6787623e7ae4a33f..1c0682aff3d1512381126cbc404857080a77b10b 100644 (file)
@@ -5,7 +5,7 @@
 .ds vr "NetHack 3.4
 .ds f0 "\*(vr
 .ds f1
-.ds f2 "October 29, 2004
+.ds f2 "January 9, 2005
 .mt
 A Guide to the Mazes of Menace
 (Guidebook for NetHack)
@@ -2244,6 +2244,9 @@ when the hero reaches the scroll_margin.
 .lp scroll_margin
 NetHack should scroll the display when the hero or cursor
 is this number of cells away from the edge of the window.
+.lp selectsaved
+NetHack should display a menu of existing saved games for the player to
+choose from at game startup, if it can. Not all ports support this option.
 .lp softkeyboard
 Display an onscreen keyboard.  Handhelds are most likely to support this option.
 .lp splash_screen
index a08aae20d3619b24505a201b246a31c360cc724e..f21a70678c63c2181f15919b028f2419f68c7802 100644 (file)
@@ -27,7 +27,7 @@
 \begin{document}
 %
 % input file: guidebook.mn
-% $Revision: 1.87 $ $Date: 2004/11/06 02:42:03 $
+% $Revision: 1.88 $ $Date: 2005/01/02 17:10:47 $
 %
 %.ds h0 "
 %.ds h1 %.ds h2 \%
@@ -40,7 +40,7 @@
 %.au
 \author{Eric S. Raymond\\
 (Extensively edited and expanded for 3.5)}
-\date{October 29, 2004}
+\date{January 9, 2005}
 
 \maketitle
 
@@ -2759,6 +2759,10 @@ when the hero reaches the scroll\_margin.
 NetHack should scroll the display when the hero or cursor
 is this number of cells away from the edge of the window.
 %.lp
+\item[\ib{selectsaved}]
+NetHack should display a menu of existing saved games for the player to
+choose from at game startup, if it can. Not all ports support this option.
+%.lp
 \item[\ib{softkeyboard}]
 Display an onscreen keyboard.  Handhelds are most likely to support this option.
 %.lp
index def7cdfa6f3894df68ab640b45de91f0242accea..4dba3a675b361bc5e6c867711cbb5b34188953fc 100644 (file)
@@ -117,6 +117,7 @@ shapeshifted vampire will transform back to vampire form after you defeat it and
        continue to fight in its native form
 container lknown flag for locked/unlocked/broken awareness
 container cknown flag for container content awareness
+plname is stored in the save file on all platforms now
 
 
 Platform- and/or Interface-Specific New Features
@@ -126,6 +127,8 @@ win32gui: menu option to add/remove windows captions
 win32gui: support for saving/restoring message history
 win32gui: added menu options "Copy ASCII Screenshot To Clipboard" and "Save 
        ASCII Screenshot To File"
+win32tty: support for 'selectsaved' option for menu of existing save files
+       to choose from at game startup
 tty: add window port routines for saving/restoring message history
 
 
index 7f8106cf3b24f3d674373a45c48d2392f90047b3..a374495849bdaa6d27f47f2c7c1a75de9f74a1eb 100644 (file)
@@ -653,6 +653,7 @@ to support:
   |  fullscreen        | WC2_FULLSCREEN     | wc2_fullscreen     |boolean |
   |  softkeyboard      | WC2_SOFTKEYBOARD   | wc2_softkeyboard   |boolean |
   |  wraptext          | WC2_WRAPTEXT       | wc2_wraptext       |boolean |
+  |  selectsaved       | WC2_SELECTSAVED    | wc2_selectsaved    |boolean |
   +--------------------+--------------------+--------------------+--------+
 
 align_message  -- where to place message window (top, bottom, left, right)
@@ -678,6 +679,7 @@ player_selection
                -- dialog or prompts for choosing character.
 popup_dialog   -- port should pop up dialog boxes for input.
 preload_tiles  -- port should preload tiles into memory.
+saveselection   -- if port can display a menu of the user's saved games do so.
 scroll_amount   -- scroll this amount when scroll_margin is reached.
 scroll_margin  -- port should scroll the display when the hero or cursor
                   is this number of cells away from the edge of the window.
index 26c91adaadbc7b03d475b58c425cfd8522b1dc9f..d35e1f5c0de805ff76d3e77e29fd5f384653859f 100644 (file)
@@ -1748,6 +1748,7 @@ E void FDECL(inven_inuse, (BOOLEAN_P));
 E int FDECL(dorecover, (int));
 E void FDECL(trickery, (char *));
 E void FDECL(getlev, (int,int,XCHAR_P,BOOLEAN_P));
+E void FDECL(get_plname_from_file, (int, char *));
 E void NDECL(minit);
 E boolean FDECL(lookup_id_mapping, (unsigned, unsigned *));
 #ifdef ZEROCOMP
@@ -1834,6 +1835,7 @@ E void FDECL(bflush, (int));
 E void FDECL(bwrite, (int,genericptr_t,unsigned int));
 E void FDECL(bclose, (int));
 E void FDECL(savefruitchn, (int,int));
+E void FDECL(store_plname_in_file, (int));
 E void NDECL(free_dungeons);
 E void NDECL(freedynamicdata);
 
index 01f77d58afc862e1c66779be856fa7bbdb1b4f87..465d0295a595e85b9832457ccb883bcbefa4a7e9 100644 (file)
@@ -259,6 +259,7 @@ struct instance_flags {
        boolean wc2_fullscreen;         /* run fullscreen */
        boolean wc2_softkeyboard;       /* use software keyboard */
        boolean wc2_wraptext;           /* wrap text */
+       boolean wc2_selectsaved;        /* display a menu of user's saved games */
        boolean  cmdassist;     /* provide detailed assistance for some commands */
        boolean  clicklook;     /* allow right-clicking for look */
        boolean  obsolete;      /* obsolete options can point at this, it isn't used */
index d96f0c177b13d7b5a39c9864025144f853877f5a..21eff4f6e0012ff0dac42511a270a970d9baf7aa 100644 (file)
 #define SELF_RECOVER           /* Allow the game itself to recover from an aborted game */
 
 #define USER_SOUNDS
+
+#ifdef WIN32CON
+#define SELECTSAVED            /* Provide menu of saved games to choose from at start */
+#endif
+
 /*
  * -----------------------------------------------------------------
  *  The remaining code shouldn't need modification.
index 8b5c8ecb1b85daa6ff79ed90890a158ec746c282..cf3b55852bb93aace55ec47c40901c2a6d6f3c4b 100644 (file)
@@ -13,7 +13,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL      18
+#define EDITLEVEL      19
 
 #define COPYRIGHT_BANNER_A \
 "NetHack, Copyright 1985-2005"
index 334e169bea6cfd4d3bccadb42dc0cb33a3cf6163..ce8169a7893ce4b0dd31a187a40e23fd7914091b 100644 (file)
@@ -203,7 +203,8 @@ extern NEARDATA struct window_procs windowprocs;
 #define WC2_SOFTKEYBOARD       0x02L   /* 02 software keyboard                      */
 #define WC2_WRAPTEXT           0x04L   /* 03 wrap long lines of text                */
 #define WC2_HILITE_STATUS      0x08L   /* 04 hilite fields in status                */ 
-                                       /* 28 free bits */
+#define WC2_SELECTSAVED                0x10L   /* 05 saved game selection menu              */
+                                       /* 27 free bits */
 
 #define ALIGN_LEFT     1
 #define ALIGN_RIGHT    2
index c8e4250c2b6a59c1ad37436517cd29ad71c80db2..713ea6c06f17813450164b1987c3ddb8588ad32b 100644 (file)
@@ -148,6 +148,10 @@ extern char *sounddir;
 extern int n_dgns;             /* from dungeon.c */
 
 #if defined(UNIX) && defined(QT_GRAPHICS)
+#define SELECTSAVED
+#endif
+
+#ifdef SELECTSAVED
 STATIC_DCL int FDECL(strcmp_wrap, (const void *, const void *));
 #endif
 STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*));
@@ -543,13 +547,17 @@ clearlocks()
 #endif
 }
 
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
 STATIC_OVL int
 strcmp_wrap(p, q)
 const void *p;
 const void *q;
 {
+#if defined(UNIX) && defined(QT_GRAPHICS)
        return strncasecmp(*(char **) p, *(char **) q, 16);
+# else
+       return strncmpi(*(char **) p, *(char **) q, 16);
+# endif
 }
 #endif
 
@@ -954,25 +962,24 @@ restore_saved_game()
        return fd;
 }
 
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
 /*ARGSUSED*/
 static char*
 plname_from_file(filename)
 const char* filename;
 {
-#ifdef STORE_PLNAME_IN_FILE
     int fd;
     char* result = 0;
 
     Strcpy(SAVEF,filename);
-#ifdef COMPRESS_EXTENSION
+#  ifdef COMPRESS_EXTENSION
     SAVEF[strlen(SAVEF)-strlen(COMPRESS_EXTENSION)] = '\0';
-#endif
+#  endif
     uncompress(SAVEF);
     if ((fd = open_savefile()) >= 0) {
        if (uptodate(fd, filename)) {
            char tplname[PL_NSIZ];
-           mread(fd, (genericptr_t) tplname, PL_NSIZ);
+           get_plname_from_file(fd, tplname);
            result = strdup(tplname);
        }
        (void) close(fd);
@@ -980,19 +987,20 @@ const char* filename;
     compress(SAVEF);
 
     return result;
-#else
-# if defined(UNIX) && defined(QT_GRAPHICS)
+# if 0
+/* --------- obsolete - used to be ifndef STORE_PLNAME_IN_FILE ----*/
+#  if defined(UNIX) && defined(QT_GRAPHICS)
     /* Name not stored in save file, so we have to extract it from
        the filename, which loses information
        (eg. "/", "_", and "." characters are lost. */
     int k;
     int uid;
     char name[64]; /* more than PL_NSIZ */
-#ifdef COMPRESS_EXTENSION
+#   ifdef COMPRESS_EXTENSION
 #define EXTSTR COMPRESS_EXTENSION
-#else
+#   else
 #define EXTSTR ""
-#endif
+#   endif
     if ( sscanf( filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name ) == 2 ) {
 #undef EXTSTR
     /* "_" most likely means " ", which certainly looks nicer */
@@ -1001,18 +1009,52 @@ const char* filename;
                name[k]=' ';
        return strdup(name);
     } else
-# endif
+#  endif /* UNIX && QT_GRAPHICS */
     {
        return 0;
     }
-#endif
+/* --------- end of obsolete code ----*/
+# endif /* 0 - WAS STORE_PLNAME_IN_FILE*/
 }
-#endif /* defined(UNIX) && defined(QT_GRAPHICS) */
+#endif /* defined(SELECTSAVED) */
 
 char**
 get_saved_games()
 {
-#if defined(UNIX) && defined(QT_GRAPHICS)
+#if defined(SELECTSAVED)
+       int n, j;
+       char **result;
+# ifdef WIN32CON
+       char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
+       char *foundfile;
+       const char *fq_save;
+
+       Sprintf(fnamebuf, "%s-", get_username(0));
+       (void)fname_encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.",
+                               '%', fnamebuf, encodedfnamebuf, BUFSZ);
+       Sprintf(SAVEF, "%s*.NetHack-saved-game", encodedfnamebuf);
+       fq_save = fqname(SAVEF, SAVEPREFIX, 0);
+
+       foundfile = foundfile_buffer();
+       if (findfirst((char *)fq_save)) {
+           n = 0;
+           do {
+               ++n;
+           } while (findnext());
+       }
+       if (n > 0) {
+           result = (char**)alloc((n+1)*sizeof(char*)); /* at most */
+           if (findfirst((char *)fq_save)) {
+           j = n = 0;
+           do {
+               char *r;
+               r = plname_from_file(foundfile);
+               if (r)
+                   result[j++] = r;
+               ++n;
+           } while (findnext());
+# endif
+# if defined(UNIX) && defined(QT_GRAPHICS)
        /* posixly correct version */
     int myuid=getuid();
     DIR *dir;
@@ -1045,6 +1087,7 @@ get_saved_games()
                    }
                }
                closedir(dir);
+# endif
                qsort(result, j, sizeof(char *), strcmp_wrap);
                result[j++] = 0;
                return result;
index de5aa1cd799be7afff9e3d24893b33213e6aba0f..f0f29dbc568f75821f4860ed66a8bd416b514dd8 100644 (file)
@@ -171,6 +171,7 @@ static struct Bool_Opt
 #else
        {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
+       {"selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME},           /*WC*/
 #ifdef EXP_ON_BOTL
        {"showexp", &flags.showexp, FALSE, SET_IN_GAME},
 #else
index fe9620103f2cc50ed65c8e61d54e5a36367ea6df..cd09df5fa78d204d18de689be2e338e32a8eed1d 100644 (file)
@@ -573,11 +573,8 @@ register int fd;
        int rtmp;
        struct obj *otmp;
 
-#ifdef STORE_PLNAME_IN_FILE
-       mread(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
-
        restoring = TRUE;
+       get_plname_from_file(fd, plname);
        getlev(fd, 0, (xchar)0, FALSE);
        if (!restgamestate(fd, &stuckid, &steedid)) {
                display_nhwindow(WIN_MESSAGE, TRUE);
@@ -656,9 +653,8 @@ register int fd;
        (void) lseek(fd, (off_t)0, 0);
 #endif
        (void) uptodate(fd, (char *)0);         /* skip version info */
-#ifdef STORE_PLNAME_IN_FILE
-       mread(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+       get_plname_from_file(fd, plname);
+
        getlev(fd, 0, (xchar)0, FALSE);
        (void) close(fd);
 
@@ -931,6 +927,17 @@ boolean ghostly;
            clear_id_mapping();
 }
 
+void
+get_plname_from_file(fd, plbuf)
+int fd;
+char *plbuf;
+{
+       int rlen, pltmpsiz = 0;
+       rlen = read(fd, (genericptr_t) &pltmpsiz, sizeof(pltmpsiz));
+       rlen = read(fd, (genericptr_t) plbuf, pltmpsiz);
+       return;
+}
+
 STATIC_OVL void
 restore_msghistory(fd)
 register int fd;
index b5deeec110f48b7f1500c991ac004be723a63870..62d2325efb85b58bae6c8614599837c6754330c0 100644 (file)
@@ -209,9 +209,7 @@ dosave0()
 #endif /* MFLOPPY */
 
        store_version(fd);
-#ifdef STORE_PLNAME_IN_FILE
-       bwrite(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+       store_plname_in_file(fd);
        ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
 #ifdef STEED
        usteed_id = (u.usteed ? u.usteed->m_id : 0);
@@ -407,9 +405,8 @@ savestateinlock()
                    (void) write(fd, (genericptr_t) &currlev, sizeof(currlev));
                    save_savefile_name(fd);
                    store_version(fd);
-#ifdef STORE_PLNAME_IN_FILE
-                   bwrite(fd, (genericptr_t) plname, PL_NSIZ);
-#endif
+                   store_plname_in_file(fd);
+
                    ustuck_id = (u.ustuck ? u.ustuck->m_id : 0);
 #ifdef STEED
                    usteed_id = (u.usteed ? u.usteed->m_id : 0);
@@ -1006,6 +1003,19 @@ register int fd, mode;
            ffruit = 0;
 }
 
+void
+store_plname_in_file(fd)
+int fd;
+{
+       int plsiztmp = PL_NSIZ;
+       bufoff(fd);
+       /* bwrite() before bufon() uses plain write() */
+       bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp));
+       bwrite(fd, (genericptr_t) plname, plsiztmp);
+       bufon(fd);
+       return;
+}
+
 STATIC_OVL void
 save_msghistory(fd, mode)
 register int fd, mode;
index cadb0489e7a0076f93d5e8d723d574a9459ad939..2725527da1905ca4b96daf908aab1e8378d4c098 100644 (file)
@@ -53,6 +53,9 @@ struct window_procs tty_procs = {
     WC_MOUSE_SUPPORT|
 #endif
     WC_COLOR|WC_HILITE_PET|WC_INVERSE|WC_EIGHT_BIT_IN,
+#if defined(SELECTSAVED) && defined(WIN32CON)
+    WC2_SELECTSAVED|
+#endif
     0L,
     tty_init_nhwindows,
     tty_player_selection,
@@ -676,6 +679,62 @@ tty_askname()
 {
     static char who_are_you[] = "Who are you? ";
     register int c, ct, tryct = 0;
+#ifdef SELECTSAVED
+# if defined(WIN32CON)
+    int ch = -2;
+    char** saved = (char **)0;
+
+    if (iflags.wc2_selectsaved)
+       saved = get_saved_games();
+    if (saved && *saved) {
+       int k, clet = 'a';
+       winid tmpwin;
+       anything any;
+       menu_item *chosen_game = (menu_item *)0;
+
+       ch = -1;
+       saved = get_saved_games();
+       tty_clear_nhwindow(BASE_WINDOW);
+       tmpwin = create_nhwindow(NHW_MENU);
+       start_menu(tmpwin);
+       any.a_int = 0;  /* no selection */
+       add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+                ATR_NONE, COPYRIGHT_BANNER_A, MENU_UNSELECTED);
+       add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+                ATR_NONE, COPYRIGHT_BANNER_B, MENU_UNSELECTED);
+       add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+                ATR_NONE, COPYRIGHT_BANNER_C, MENU_UNSELECTED);
+       add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+                ATR_NONE, "", MENU_UNSELECTED);
+       add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
+                ATR_NONE, "Select one of your saved games", MENU_UNSELECTED);
+       for (k = 0; saved[k]; ++k) {
+               if (clet == 'z' + 1) clet = 'A';
+               if (clet == 'Z') break;
+               any.a_int = k + 1;
+               add_menu(tmpwin, NO_GLYPH, &any, clet++, 0,
+                        ATR_NONE, saved[k], MENU_UNSELECTED);
+        }
+       any.a_int = -2;
+       add_menu(tmpwin, NO_GLYPH, &any, clet, 0,
+                ATR_NONE, "Start a new character", MENU_UNSELECTED);
+       /* no prompt on end_menu, as we've done our own at the top */
+       end_menu(tmpwin, (char *)0);
+       if (select_menu(tmpwin, PICK_ONE, &chosen_game) > 0) {
+               ch = chosen_game->item.a_int;
+               if (ch > 0)  {
+                       ch--;
+                       strcpy(plname,saved[ch]);
+               }
+               free((genericptr_t)chosen_game);
+        }
+       destroy_nhwindow(tmpwin);
+    }
+    free_saved_games(saved);
+    if (ch >= 0) return;
+    if (ch == -1) bail("Until next time then...");
+# endif /* WIN32CON */
+#endif /* SELECTSAVED */
 
     tty_putstr(BASE_WINDOW, 0, "");
     do {
@@ -1555,8 +1614,10 @@ tty_display_nhwindow(window, blocking)
            } else
                clear_screen();
            ttyDisplay->toplin = 0;
-       } else
-           tty_clear_nhwindow(WIN_MESSAGE);
+       } else {
+               if (WIN_MESSAGE != WIN_ERR)
+                       tty_clear_nhwindow(WIN_MESSAGE);
+       }
 
        if (cw->data || !cw->maxrow)
            process_text_window(window, cw);