};
#endif /* WINCHAIN */
+#ifdef SAFEPROCS
+/*
+ * window port routines available in sys/share/safeproc.c
+ */
+extern struct window_procs *FDECL(get_safe_procs, (int));
+extern void FDECL(safe_init_nhwindows, (int *, char **));
+extern void NDECL(safe_player_selection);
+extern void NDECL(safe_askname);
+extern void NDECL(safe_get_nh_event);
+extern void FDECL(safe_exit_nhwindows, (const char *));
+extern void FDECL(safe_suspend_nhwindows, (const char *));
+extern void NDECL(safe_resume_nhwindows);
+extern winid FDECL(safe_create_nhwindow, (int));
+extern void FDECL(safe_clear_nhwindow, (winid));
+extern void FDECL(safe_display_nhwindow, (winid, BOOLEAN_P));
+extern void FDECL(safe_destroy_nhwindow, (winid));
+extern void FDECL(safe_curs, (winid, int, int));
+extern void FDECL(safe_putstr, (winid, int, const char *));
+extern void FDECL(safe_putmixed, (winid, int, const char *));
+extern void FDECL(safe_display_file, (const char *, BOOLEAN_P));
+extern void FDECL(safe_start_menu, (winid));
+extern void FDECL(safe_add_menu, (winid, int, const ANY_P *, CHAR_P, CHAR_P,
+ int, const char *, BOOLEAN_P));
+extern void FDECL(safe_end_menu, (winid, const char *));
+extern int FDECL(safe_select_menu, (winid, int, MENU_ITEM_P **));
+extern char FDECL(safe_message_menu, (CHAR_P, int, const char *));
+extern void NDECL(safe_update_inventory);
+extern void NDECL(safe_mark_synch);
+extern void NDECL(safe_wait_synch);
+#ifdef CLIPPING
+extern void FDECL(safe_cliparound, (int, int));
+#endif
+#ifdef POSITIONBAR
+extern void FDECL(safe_update_positionbar, (char *));
+#endif
+extern void FDECL(safe_print_glyph, (winid, XCHAR_P, XCHAR_P, int, int));
+extern void FDECL(safe_raw_print, (const char *));
+extern void FDECL(safe_raw_print_bold, (const char *));
+extern int NDECL(safe_nhgetch);
+extern int FDECL(safe_nh_poskey, (int *, int *, int *));
+extern void NDECL(safe_nhbell);
+extern int NDECL(safe_doprev_message);
+extern char FDECL(safe_yn_function, (const char *, const char *, CHAR_P));
+extern void FDECL(safe_getlin, (const char *, char *));
+extern int NDECL(safe_get_ext_cmd);
+extern void FDECL(safe_number_pad, (int));
+extern void NDECL(safe_delay_output);
+#ifdef CHANGE_COLOR
+extern void FDECL(safe_change_color, (int, long, int));
+#ifdef MAC
+extern void FDECL(safe_change_background, (int));
+extern short FDECL(safe_set_font_name, (winid, char *));
+#endif
+extern char *NDECL(safe_get_color_string);
+#endif
+extern void NDECL(safe_start_screen);
+extern void NDECL(safe_end_screen);
+extern void FDECL(safe_outrip, (winid, int, time_t));
+extern void FDECL(safe_preference_update, (const char *));
+extern char *FDECL(safe_getmsghistory, (BOOLEAN_P));
+extern void FDECL(safe_putmsghistory, (const char *, BOOLEAN_P));
+extern void NDECL(safe_status_init);
+extern void NDECL(safe_status_finish);
+extern void FDECL(safe_status_enablefield,
+ (int, const char *, const char *, BOOLEAN_P));
+extern void FDECL(safe_status_update, (int, genericptr_t, int, int, int, unsigned long *));
+extern boolean NDECL(safe_can_suspend);
+extern void FDECL(stdio_raw_print, (const char *));
+extern void FDECL(stdio_raw_print_bold, (const char *));
+extern void NDECL(stdio_wait_synch);
+extern int NDECL(stdio_nhgetch);
+#endif /* SAFEPROCS */
#endif /* WINPROCS_H */
+
* A multi-interface binary might only support status highlighting
* for some of the interfaces; check whether we asked for it but are
* using one which doesn't.
+ *
+ * Option processing can take place before a user-decided WindowPort
+ * is even initialized, so check for that too.
*/
- if (iflags.hilite_delta && !wc2_supported("statushilites")) {
- raw_printf("Status highlighting not supported for %s interface.",
- windowprocs.name);
- iflags.hilite_delta = 0;
+ if (!WINDOWPORT("safe-startup")) {
+ if (iflags.hilite_delta && !wc2_supported("statushilites")) {
+ raw_printf("Status highlighting not supported for %s interface.",
+ windowprocs.name);
+ iflags.hilite_delta = 0;
+ }
}
#endif
return;
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
-/* main.c - MSDOS, OS/2, ST, Amiga, and Windows NetHack */
-
-#ifdef WIN32
-#include "win32api.h" /* for GetModuleFileName */
-#endif
+/* main.c - MSDOS, OS/2, ST, Amiga NetHack */
#include "hack.h"
#include "dlb.h"
STATIC_DCL void FDECL(process_options, (int argc, char **argv));
STATIC_DCL void NDECL(nhusage);
-#if defined(MICRO) || defined(WIN32) || defined(OS2)
+#if defined(MICRO) || defined(OS2)
extern void FDECL(nethack_exit, (int));
#else
#define nethack_exit exit
#endif
-#ifdef WIN32
-extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
-extern int redirect_stdout; /* from sys/share/pcsys.c */
-extern int GUILaunched;
-char *NDECL(exename);
-char default_window_sys[] = "mswin";
-#ifndef WIN32CON
-HANDLE hStdOut;
-boolean NDECL(fakeconsole);
-void NDECL(freefakeconsole);
-#endif
-#endif
-
-#if defined(MSWIN_GRAPHICS)
-extern void NDECL(mswin_destroy_reg);
-#endif
-
#ifdef EXEPATH
STATIC_DCL char *FDECL(exepath, (char *));
#endif
extern boolean FDECL(pcmain, (int, char **));
-#if defined(__BORLANDC__) && !defined(_WIN32)
+#if defined(__BORLANDC__)
void NDECL(startup);
unsigned _stklen = STKSIZ;
#endif
{
boolean resuming;
- nethack_enter(argc, argv);
-
sys_early_init();
-#if defined(WIN32) && defined(TTY_GRAPHICS)
- Strcpy(default_window_sys, "tty");
-#else
-#if defined(CURSES_GRAPHICS)
- Strcpy(default_window_sys, "curses");
-#endif
-#endif
-
resuming = pcmain(argc, argv);
-#ifdef LAN_FEATURES
- init_lan_features();
-#endif
moveloop(resuming);
nethack_exit(EXIT_SUCCESS);
/*NOTREACHED*/
{
register int fd;
register char *dir;
-#if defined(WIN32) || defined(MSDOS)
+#if defined(MSDOS)
char *envp = NULL;
char *sptr = NULL;
#endif
-#if defined(WIN32)
- char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
- boolean save_getreturn_status = getreturn_enabled;
-#endif
#ifdef NOCWD_ASSUMPTIONS
char failbuf[BUFSZ];
#endif
# endif
#endif
-#if defined(__BORLANDC__) && !defined(_WIN32)
+#if defined(__BORLANDC__)
startup();
#endif
#endif
hname = "NetHack"; /* used for syntax messages */
-#ifndef WIN32
choose_windows(DEFAULT_WINDOW_SYS);
-#else
- choose_windows(default_window_sys);
- if (argc >= 1
- && !strcmpi(default_window_sys, "mswin")
- && strstri(argv[0], "nethackw.exe"))
- iflags.windowtype_locked = TRUE;
-#endif
#if !defined(AMIGA) && !defined(GNUDOS)
/* Save current directory and make sure it gets restored when
for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++)
fqn_prefix[prefcnt] = fqn_prefix[0];
-#if defined(WIN32) || defined(MSDOS)
+#if defined(MSDOS)
/* sysconf should be searched for in this location */
envp = nh_getenv("COMMONPROGRAMFILES");
if (envp) {
chdirx(HACKDIR, 1);
#endif
ami_wininit_data();
-#endif
-#ifdef WIN32
- save_getreturn_status = getreturn_enabled;
-#ifdef TTY_GRAPHICS
- raw_clear_screen();
-#endif
- getreturn_enabled = TRUE;
- check_recordfile((char *) 0);
#endif
initoptions();
argv++;
}
-#ifdef WIN32
- if (argcheck(argc, argv, ARG_WINDOWS) == 1) {
- argc--;
- argv++;
- }
-#endif
-
if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
/* avoid matching "-dec" for DECgraphics; since the man page
* says -d directory, hope nobody's using -desomething_else
Strcpy(hackdir, dir);
}
if (argc > 1) {
-#if defined(WIN32) && !defined(WIN32CON)
- int sfd = 0;
- boolean tmpconsole = FALSE;
- hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-#endif
/*
* Now we know the directory containing 'record' and
* may do a prscore().
*/
if (!strncmp(argv[1], "-s", 2)) {
-#if defined(WIN32) && !defined(WIN32CON)
-
-#if 0
- if (!hStdOut) {
- tmpconsole = fakeconsole();
- }
-#endif
- /*
- * Check to see if we're redirecting to a file.
- */
- sfd = (int) _fileno(stdout);
- redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0;
-
- if (!redirect_stdout && !hStdOut) {
- raw_printf(
- "-s is not supported for the Graphical Interface\n");
- nethack_exit(EXIT_SUCCESS);
- }
-#endif
-
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
chdirx(hackdir, 0);
#endif
initoptions();
#endif
prscore(argc, argv);
-#if defined(WIN32) && !defined(WIN32CON)
- if (tmpconsole) {
- getreturn("to exit");
- freefakeconsole();
- tmpconsole = FALSE;
- }
-#endif
nethack_exit(EXIT_SUCCESS);
}
-#ifdef MSWIN_GRAPHICS
- if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */
- mswin_destroy_reg();
- nethack_exit(EXIT_SUCCESS);
- }
-#endif
/* Don't initialize the window system just to print usage */
if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
-#if 0
- if (!hStdOut) {
- GUILaunched = 0;
- tmpconsole = fakeconsole();
- }
-#endif
nhusage();
-
-#if defined(WIN32) && !defined(WIN32CON)
- if (tmpconsole) {
- getreturn("to exit");
- freefakeconsole();
- tmpconsole = FALSE;
- }
-#endif
nethack_exit(EXIT_SUCCESS);
}
}
}
-
-#ifdef WIN32
- getreturn_enabled = save_getreturn_status;
-#endif
/*
* It seems you really want to play.
*/
"\"%s\".%s",
copyright_banner_line(1), copyright_banner_line(2),
copyright_banner_line(3), copyright_banner_line(4), DLBFILE,
-#ifdef WIN32
- "\nAre you perhaps trying to run NetHack within a zip utility?");
-#else
"");
-#endif
error("dlb_init failure.");
}
chdirx(hackdir, 1);
#endif
-#if defined(MSDOS) || defined(WIN32)
+#if defined(MSDOS)
/* In 3.6.0, several ports process options before they init
* the window port. This allows settings that impact window
* ports to be specified or read from the sys or user config files.
*/
process_options(argc, argv);
-#ifdef WIN32
- /*
- if (WINDOWPORT("mswin"))
- NHWinMainInit();
- else
- */
-#ifdef TTY_GRAPHICS
- if (WINDOWPORT("tty")) {
- iflags.use_background_glyph = FALSE;
- nttty_open(1);
- } else {
- iflags.use_background_glyph = TRUE;
- }
-#endif /* TTY_GRAPHICS */
-#endif /* WIN32 */
-#endif /* MSDOS || WIN32 */
+#endif /* MSDOS */
-#if defined(MSDOS) || defined(WIN32)
+#if defined(MSDOS)
init_nhwindows(&argc, argv);
#else
init_nhwindows(&argc, argv);
process_options(argc, argv);
#endif
-#if defined(WIN32) && defined(TTY_GRAPHICS)
- toggle_mouse_support(); /* must come after process_options */
-#endif
-
#ifdef MFLOPPY
set_lock_and_bones();
#ifndef AMIGA
* overwritten without confirmation when a user starts up
* another game with the same player name.
*/
-#if defined(WIN32)
- /* Obtain the name of the logged on user and incorporate
- * it into the name. */
- Sprintf(fnamebuf, "%s-%s", get_username(0), plname);
- (void) fname_encode(
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%',
- fnamebuf, encodedfnamebuf, BUFSZ);
- Sprintf(lock, "%s", encodedfnamebuf);
- /* regularize(lock); */ /* we encode now, rather than substitute */
-#else
Strcpy(lock, plname);
regularize(lock);
-#endif
getlock();
#else /* What follows is !PC_LOCKING */
#ifdef AMIGA /* We'll put the bones & levels in the user specified directory \
if (fd < 0) {
raw_print("Cannot create lock file");
} else {
-#ifdef WIN32
- hackpid = GetCurrentProcessId();
-#else
hackpid = 1;
-#endif
write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
nhclose(fd);
}
vision_init();
display_gamewindows();
-#ifdef WIN32
- getreturn_enabled = TRUE;
-#endif
-
/*
* First, try to find and restore a save file for specified character.
* We'll return here if new game player_selection() renames the hero.
case 'l':
bigscreen = -1;
break;
-#endif
-#ifdef WIN32
- case 'w': /* windowtype */
-#ifdef TTY_GRAPHICS
- if (strncmpi(&argv[0][2], "tty", 3)) {
- nttty_open(1);
- }
-#endif
- config_error_init(FALSE, "command line", FALSE);
- choose_windows(&argv[0][2]);
- config_error_done();
- break;
#endif
case '@':
flags.randomall = 1;
#endif /* CHDIR */
#ifdef PORT_HELP
-#if defined(MSDOS) || defined(WIN32)
+#if defined(MSDOS)
void
port_help()
{
/* display port specific help file */
display_file(PORT_HELP, 1);
}
-#endif /* MSDOS || WIN32 */
+#endif /* MSDOS */
#endif /* PORT_HELP */
/* validate wizard mode if player has requested access to it */
#define PATH_SEPARATOR '\\'
#endif
-#if defined(WIN32) && !defined(WIN32CON)
-static char exenamebuf[PATHLEN];
-extern HANDLE hConIn;
-extern HANDLE hConOut;
-boolean has_fakeconsole;
-
-char *
-exename()
-{
- int bsize = PATHLEN;
- char *tmp = exenamebuf, *tmp2;
-
-#ifdef UNICODE
- {
- TCHAR wbuf[PATHLEN * 4];
- GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4);
- WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
- }
-#else
- *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
-#endif
- tmp2 = strrchr(tmp, PATH_SEPARATOR);
- if (tmp2)
- *tmp2 = '\0';
- tmp2++;
- return tmp2;
-}
-
-boolean
-fakeconsole(void)
-{
- if (!hStdOut) {
- HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
- HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
-
- if (!hStdOut && !hStdIn) {
- /* Bool rval; */
- AllocConsole();
- AttachConsole(GetCurrentProcessId());
- /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
- freopen("CON", "w", stdout);
- freopen("CON", "r", stdin);
- }
- has_fakeconsole = TRUE;
- }
-
- /* Obtain handles for the standard Console I/O devices */
- hConIn = GetStdHandle(STD_INPUT_HANDLE);
- hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
-#if 0
- if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
- /* Unable to set control handler */
- cmode = 0; /* just to have a statement to break on for debugger */
- }
-#endif
- return has_fakeconsole;
-}
-void freefakeconsole()
-{
- if (has_fakeconsole) {
- FreeConsole();
- }
-}
-#endif
-
#define EXEPATHBUFSZ 256
char exepathbuf[EXEPATHBUFSZ];
return (char *) 0;
bsize = EXEPATHBUFSZ;
tmp = exepathbuf;
-#ifndef WIN32
Strcpy(tmp, str);
-#else
-#ifdef UNICODE
- {
- TCHAR wbuf[BUFSZ];
- GetModuleFileName((HANDLE) 0, wbuf, BUFSZ);
- WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
- }
-#else
- *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
-#endif
-#endif
tmp2 = strrchr(tmp, PATH_SEPARATOR);
if (tmp2)
*tmp2 = '\0';
--- /dev/null
+/* NetHack 3.6 safeproc.c */
+/* Copyright (c) Michael Allison, 2018 */
+/* NetHack may be freely redistributed. See license for details. */
+
+#include "hack.h"
+#include <stdio.h>
+
+/*
+ * ***********************************************************
+ * This is a complete WindowPort implementation that can be
+ * assigned to the windowproc function pointers very early
+ * in the startup initialization, perhaps immediately even.
+ * It requires only the following call:
+ * windowprocs = get_safe_procs(0);
+ *
+ * The game startup can trigger functions in other modules
+ * that make assumptions on a WindowPort being available
+ * and bad things can happen if any function pointers are
+ * null at that time.
+ *
+ * Some ports prior to 3.6.2 made attempts to early init
+ * various pieces of one of their WindowPorts, but that
+ * caused conflicts if that particular WindowPort wasn't
+ * the one that the user ended up selecting in their
+ * config file later. The WindowPort interfaced was designed
+ * to allow multiple WindowPorts to be linked into the same
+ * game binary.
+ *
+ * The base functions established by a call to get_safe_procs()
+ * accomplish the goal of preventing crashes, but not much
+ * else.
+ *
+ * There are also a few additional functions provided in here
+ * that can be selected optionally to provide some startup
+ * functionality for getting messages out to the user about
+ * issues that are being experienced during startup in
+ * general or during options parsing. The ones in here are
+ * deliberately free from any platforms or OS specific code.
+ * Please leave them using stdio C routines as much as
+ * possible. That isn't to say you can't do fancier functions
+ * prior to initialization of the primary WindowPort, but you
+ * can provide those platform-specific functions elsewhere,
+ * and assign them the same way that these more generic versions
+ * are assigned.
+ *
+ * The additional platform-independent, but more functional
+ * routines provided in here should be assigned after the
+ * windowprocs = get_safe_procs()
+ * call. Here's a list of them:
+ *
+ *
+ *
+ *
+ * ***********************************************************
+ */
+
+struct window_procs safe_procs = {
+ "safe-startup", 0L, 0L,
+ safe_init_nhwindows, safe_player_selection, safe_askname, safe_get_nh_event,
+ safe_exit_nhwindows, safe_suspend_nhwindows, safe_resume_nhwindows,
+ safe_create_nhwindow, safe_clear_nhwindow, safe_display_nhwindow,
+ safe_destroy_nhwindow, safe_curs, safe_putstr, genl_putmixed,
+ safe_display_file, safe_start_menu, safe_add_menu, safe_end_menu,
+ safe_select_menu, safe_message_menu, safe_update_inventory, safe_mark_synch,
+ safe_wait_synch,
+#ifdef CLIPPING
+ safe_cliparound,
+#endif
+#ifdef POSITIONBAR
+ safe_update_positionbar,
+#endif
+ safe_print_glyph, safe_raw_print, safe_raw_print_bold, safe_nhgetch,
+ safe_nh_poskey, safe_nhbell, safe_doprev_message, safe_yn_function,
+ safe_getlin, safe_get_ext_cmd, safe_number_pad, safe_delay_output,
+#ifdef CHANGE_COLOR /* the Mac uses a palette device */
+ safe_change_color,
+#ifdef MAC
+ safe_change_background, set_safe_font_name,
+#endif
+ safe_get_color_string,
+#endif
+ safe_start_screen, safe_end_screen, genl_outrip,
+ safe_preference_update,
+ safe_getmsghistory, safe_putmsghistory,
+ safe_status_init,
+ safe_status_finish, safe_status_enablefield,
+#ifdef STATUS_HILITES
+ safe_status_update,
+#else
+ safe_status_update,
+#endif
+ safe_can_suspend,
+};
+
+struct window_procs *
+get_safe_procs(optn)
+int optn;
+{
+ if (optn) {
+ /* include the slightly more functional stdc versions */
+ safe_procs.win_raw_print = stdio_raw_print;
+ safe_procs.win_raw_print_bold = stdio_raw_print_bold;
+ safe_procs.win_nhgetch = stdio_nhgetch;
+ safe_procs.win_wait_synch = stdio_wait_synch;
+ }
+ return &safe_procs;
+}
+
+/*ARGSUSED*/
+void
+safe_init_nhwindows(argcp, argv)
+int *argcp UNUSED;
+char **argv UNUSED;
+{
+ return;
+}
+
+void
+safe_player_selection()
+{
+ return;
+}
+
+void
+safe_askname()
+{
+ return;
+}
+
+void
+safe_get_nh_event()
+{
+ return;
+}
+
+void
+safe_suspend_nhwindows(str)
+const char *str;
+{
+ return;
+}
+
+void
+safe_resume_nhwindows()
+{
+ return;
+}
+
+void
+safe_exit_nhwindows(str)
+const char *str;
+{
+ return;
+}
+
+winid
+safe_create_nhwindow(type)
+int type;
+{
+ return WIN_ERR;
+}
+
+void
+safe_clear_nhwindow(window)
+winid window;
+{
+ return;
+}
+
+/*ARGSUSED*/
+void
+safe_display_nhwindow(window, blocking)
+winid window;
+boolean blocking;
+{
+ return;
+}
+
+void
+safe_dismiss_nhwindow(window)
+winid window;
+{
+ return;
+}
+
+void
+safe_destroy_nhwindow(window)
+winid window;
+{
+ return;
+}
+
+void
+safe_curs(window, x, y)
+winid window;
+int x, y;
+{
+ return;
+}
+
+void
+safe_putstr(window, attr, str)
+winid window;
+int attr;
+const char *str;
+{
+ return;
+}
+
+void
+safe_display_file(fname, complain)
+const char *fname;
+boolean complain;
+{
+ return;
+}
+
+void
+safe_start_menu(window)
+winid window;
+{
+ return;
+}
+
+/*ARGSUSED*/
+/*
+ * Add a menu item to the beginning of the menu list. This list is reversed
+ * later.
+ */
+void
+safe_add_menu(window, glyph, identifier, ch, gch, attr, str, preselected)
+winid window; /* window to use, must be of type NHW_MENU */
+int glyph UNUSED; /* glyph to display with item (not used) */
+const anything *identifier; /* what to return if selected */
+char ch; /* keyboard accelerator (0 = pick our own) */
+char gch; /* group accelerator (0 = no group) */
+int attr; /* attribute for string (like safe_putstr()) */
+const char *str; /* menu string */
+boolean preselected; /* item is marked as selected */
+{
+ return;
+}
+
+/*
+ * End a menu in this window, window must a type NHW_MENU.
+ */
+void
+safe_end_menu(window, prompt)
+winid window; /* menu to use */
+const char *prompt; /* prompt to for menu */
+{
+ return;
+}
+
+int
+safe_select_menu(window, how, menu_list)
+winid window;
+int how;
+menu_item **menu_list;
+{
+ return 0;
+}
+
+/* special hack for treating top line --More-- as a one item menu */
+char
+safe_message_menu(let, how, mesg)
+char let;
+int how;
+const char *mesg;
+{
+ return '\033';
+}
+
+void
+safe_update_inventory()
+{
+ return;
+}
+
+void
+safe_mark_synch()
+{
+}
+
+void
+safe_wait_synch()
+{
+}
+
+#ifdef CLIPPING
+void
+safe_cliparound(x, y)
+int x, y;
+{
+}
+#endif /* CLIPPING */
+
+/*
+ * safe_print_glyph
+ *
+ * Print the glyph to the output device. Don't flush the output device.
+ */
+void
+safe_print_glyph(window, x, y, glyph, bkglyph)
+winid window;
+xchar x, y;
+int glyph;
+int bkglyph UNUSED;
+{
+ return;
+}
+
+void
+safe_raw_print(str)
+const char *str;
+{
+ return;
+}
+
+void
+safe_raw_print_bold(str)
+const char *str;
+{
+ return;
+}
+
+int
+safe_nhgetch()
+{
+ return '\033';
+}
+
+/*
+ * return a key, or 0, in which case a mouse button was pressed
+ * mouse events should be returned as character postitions in the map window.
+ * Since normal tty's don't have mice, just return a key.
+ */
+/*ARGSUSED*/
+int
+safe_nh_poskey(x, y, mod)
+int *x, *y, *mod;
+{
+ return '\033';
+}
+
+void
+win_safe_init(dir)
+int dir;
+{
+ return;
+}
+
+#ifdef POSITIONBAR
+void
+safe_update_positionbar(posbar)
+char *posbar;
+{
+ return;
+}
+#endif /* POSITIONBAR */
+
+/*
+ * safe_status_init()
+ * -- initialize the port-specific data structures.
+ */
+void
+safe_status_init()
+{
+ return;
+}
+
+void
+safe_can_suspend()
+{
+ return;
+}
+
+void
+safe_nhbell()
+{
+ return;
+}
+
+int
+safe_doprev_message()
+{
+ return 0;
+}
+
+char
+safe_yn_function(query, resp, def)
+const char *query;
+const char *resp;
+char def;
+{
+ return '\033';
+}
+
+/*ARGSUSED*/
+static void
+safe_getlin(prompt, outbuf)
+const char *prompt UNUSED;
+char *outbuf;
+{
+ Strcpy(outbuf, "\033");
+}
+
+int
+safe_get_ext_cmd()
+{
+ return '\033';
+}
+
+void
+safe_number_pad(mode)
+int mode;
+{
+ return;
+}
+
+void
+safe_delay_output()
+{
+ return;
+}
+
+void
+safe_start_screen()
+{
+ return;
+}
+
+void
+safe_end_screen()
+{
+ return;
+}
+
+void
+safe_outrip(tmpwin, how, when)
+winid tmpwin;
+int how;
+time_t when;
+{
+ return;
+}
+
+/*ARGSUSED*/
+void
+safe_preference_update(pref)
+const char *pref UNUSED;
+{
+ return;
+}
+
+char *
+safe_getmsghistory(init)
+boolean init UNUSED;
+{
+ return (char *) 0;
+}
+
+void
+safe_putmsghistory(msg, is_restoring)
+const char *msg;
+boolean is_restoring;
+{
+}
+
+void
+safe_status_finish()
+{
+}
+
+void
+safe_status_enablefield(fieldidx, nm, fmt, enable)
+int fieldidx;
+const char *nm;
+const char *fmt;
+boolean enable;
+{
+}
+
+#ifdef STATUS_HILITES
+/* call once for each field, then call with BL_FLUSH to output the result */
+void
+safe_status_update(idx, ptr, chg, percent, color, colormasks)
+int idx;
+genericptr_t ptr;
+int chg UNUSED, percent UNUSED, color UNUSED;
+unsigned long *colormasks UNUSED;
+{
+}
+#endif /* STATUS_HILITES */
+
+/**************************************************************
+ * These are some optionally selectable routines that add
+ * some base functionality over the safe_* versions above.
+ * The safe_* versions are primarily designed to ensure that
+ * there are no null function pointers remaining at early
+ * game startup/initialization time.
+ *
+ * The slightly more functional versions in here should be kept
+ * free of platform-specific code or OS-specific code. If you
+ * want to use versions that involve platform-specific or
+ * OS-specific code, go right ahead but use your own replacement
+ * version of the functions in a platform-specific or
+ * OS-specific source file, not in here.
+ ***************************************************************/
+
+/* Add to your code: windowprocs.win_raw_print = stdio_wait_synch; */
+void
+stdio_wait_synch()
+{
+ char valid[] = {' ', '\n', '\r', '\033', '\0'};
+
+ fprintf(stdout, "--More--");
+ (void) fflush(stdout);
+ while (!index(valid, stdio_nhgetch()))
+ ;
+}
+
+/* Add to your code: windowprocs.win_raw_print = stdio_raw_print; */
+void
+stdio_raw_print(str)
+const char *str;
+{
+ if (str)
+ fprintf(stdout, "%s\n", str);
+ return;
+}
+
+/* Add to your code: windowprocs.win_raw_print_bold = stdio_raw_print_bold; */
+void
+stdio_raw_print_bold(str)
+const char *str;
+{
+ stdio_raw_print(str);
+ return;
+}
+
+/* Add to your code: windowprocs.win_nhgetch = stdio_nhgetch; */
+int
+stdio_nhgetch()
+{
+ return getchar();
+}
+
+
+/* safeprocs.c */
VOBJ07 = $(O)end.o $(O)engrave.o $(O)exper.o $(O)explode.o
VOBJ08 = $(O)extralev.o $(O)files.o $(O)fountain.o $(O)hack.o
VOBJ09 = $(O)hacklib.o $(O)invent.o $(O)light.o $(O)lock.o
-VOBJ10 = $(O)mail.o $(O)pcmain.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o
+VOBJ10 = $(O)mail.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o
VOBJ11 = $(O)mhitm.o $(O)mhitu.o $(O)minion.o $(O)mklev.o
VOBJ12 = $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o
VOBJ13 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o
VOBJ25 = $(O)vault.o $(O)vis_tab.o $(O)vision.o $(O)weapon.o
VOBJ26 = $(O)were.o $(O)wield.o $(O)windows.o $(O)wizard.o
VOBJ27 = $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o
-VOBJ28 = $(O)win10.o
+VOBJ28 = $(O)win10.o $(O)safeproc.o $(O)windmain.o
DLBOBJ = $(O)dlb.o
# Util builds
#==========================================
-cflagsBuild = $(cflags) $(INCLDIR) $(WINPFLAG) $(DLBFLG)
+cflagsBuild = $(cflags) $(INCLDIR) $(WINPFLAG) $(DLBFLG) -DSAFEPROCS
lflagsBuild = $(lflags) $(conlibs) $(MACHINE)
#==========================================
#
$(O)winhack.o: $(HACK_H) $(MSWIN)\winhack.c
- @$(cc) $(cflagsBuild) -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c
+ @$(cc) $(cflagsBuild) -DSAFEPROCS -I$(MSWSYS) -I$(MSWIN) -Fo$@ $(MSWIN)\winhack.c
#if you aren't linking in the full tty then
#include the following stub for proper linkage.
$(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\atari\tos.c
-$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h \
- $(MSWSYS)\win32api.h
- @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcmain.c
+$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
+$(O)safeprocs.o: ..\sys\share\safeprocs.c $(HACK_H) $(MSWSYS)\win32api.h
+ @$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\safeprocs.c
$(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H)
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pcsys.c
$(O)pctty.o: ..\sys\share\pctty.c $(HACK_H)
return;
}
-#ifdef TTY_GRAPHICS
void
backsp()
{
return;
}
-#endif
int
has_color(int color)
--- /dev/null
+/* NetHack 3.6 windmain.c $NHDT-Date: 1543465755 2018/11/29 04:29:15 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.101 $ */
+/* Copyright (c) Derek S. Ray, 2015. */
+/* NetHack may be freely redistributed. See license for details. */
+
+/* main.c - Windows */
+
+#include "win32api.h" /* for GetModuleFileName */
+#include "hack.h"
+#include "dlb.h"
+#include <ctype.h>
+#include <sys\stat.h>
+
+#if !defined(SAFEPROCS)
+#error You must #define SAFEPROCS to build windmain.c
+#endif
+
+#define E extern
+static void FDECL(process_options, (int argc, char **argv));
+static void NDECL(nhusage);
+static char *FDECL(exepath, (char *));
+char *NDECL(exename);
+boolean NDECL(fakeconsole);
+void NDECL(freefakeconsole);
+E void FDECL(nethack_exit, (int));
+#if defined(MSWIN_GRAPHICS)
+E void NDECL(mswin_destroy_reg);
+#endif
+#undef E
+
+int NDECL(windows_nhgetch);
+void NDECL(windows_nhbell);
+int FDECL(windows_nh_poskey, (int *, int *, int *));
+void FDECL(windows_raw_print, (const char *));
+char FDECL(windows_yn_function, (const char *, const char *, CHAR_P));
+void FDECL(windows_getlin, (const char *, char *));
+
+char orgdir[PATHLEN];
+extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
+extern int redirect_stdout; /* from sys/share/pcsys.c */
+extern int GUILaunched;
+HANDLE hStdOut;
+#if defined(MSWIN_GRAPHICS)
+char default_window_sys[] = "mswin";
+#endif
+
+/*
+ * __MINGW32__ Note
+ * If the graphics version is built, we don't need a main; it is skipped
+ * to help MinGW decide which entry point to choose. If both main and
+ * WinMain exist, the resulting executable won't work correctly.
+ */
+int
+#ifndef __MINGW32__
+main(argc, argv)
+#else
+mingw_main(argc, argv)
+#endif
+int argc;
+char *argv[];
+{
+ boolean save_getreturn_status = getreturn_enabled;
+ boolean resuming = FALSE; /* assume new game */
+ register int fd;
+ register char *dir;
+ char *envp = NULL;
+ char *sptr = NULL;
+ char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
+ char failbuf[BUFSZ];
+
+ /*
+ * Get a set of valid safe windowport function
+ * pointers during early startup initialization.
+ */
+ if (!WINDOWPORT("safe-startup"))
+ windowprocs = *get_safe_procs(1);
+ sys_early_init();
+#ifdef _MSC_VER
+# ifdef DEBUG
+ /* set these appropriately for VS debugging */
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ERROR,
+ _CRTDBG_MODE_DEBUG); /* | _CRTDBG_MODE_FILE);*/
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
+/*| _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW);*/
+/* use STDERR by default
+_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
+/* Heap Debugging
+ _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
+ | _CRTDBG_ALLOC_MEM_DF
+ | _CRTDBG_CHECK_ALWAYS_DF
+ | _CRTDBG_CHECK_CRT_DF
+ | _CRTDBG_DELAY_FREE_MEM_DF
+ | _CRTDBG_LEAK_CHECK_DF);
+ _CrtSetBreakAlloc(1423);
+*/
+# endif
+#endif
+
+ hname = "NetHack"; /* used for syntax messages */
+ /* Save current directory and make sure it gets restored when
+ * the game is exited.
+ */
+ if (getcwd(orgdir, sizeof orgdir) == (char *) 0)
+ error("NetHack: current directory path too long");
+ dir = nh_getenv("NETHACKDIR");
+ if (dir == (char *) 0)
+ dir = nh_getenv("HACKDIR");
+ if (dir == (char *) 0)
+ dir = exepath(argv[0]);
+#ifdef _MSC_VER
+ if (IsDebuggerPresent()) {
+ static char exepath[_MAX_PATH];
+ /* check if we're running under the debugger so we can get to the right folder anyway */
+ if (dir != (char *)0) {
+ char *top = (char *)0;
+
+ if (strlen(dir) < (_MAX_PATH - 1))
+ strcpy(exepath, dir);
+ top = strstr(exepath, "\\build\\.\\Debug");
+ if (!top) top = strstr(exepath, "\\build\\.\\Release");
+ if (top) {
+ *top = '\0';
+ if (strlen(exepath) < (_MAX_PATH - (strlen("\\binary\\") + 1))) {
+ Strcat(exepath, "\\binary\\");
+ if (strlen(exepath) < (PATHLEN - 1)) {
+ dir = exepath;
+ }
+ }
+ }
+ }
+ }
+#endif
+ if (dir != (char *)0) {
+ int prefcnt;
+ int fd;
+ boolean have_syscf = FALSE;
+
+ (void) strncpy(hackdir, dir, PATHLEN - 1);
+ hackdir[PATHLEN - 1] = '\0';
+ fqn_prefix[0] = (char *) alloc(strlen(hackdir) + 2);
+ Strcpy(fqn_prefix[0], hackdir);
+ append_slash(fqn_prefix[0]);
+ for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++)
+ fqn_prefix[prefcnt] = fqn_prefix[0];
+ /* sysconf should be searched for in this location */
+ envp = nh_getenv("COMMONPROGRAMFILES");
+ if (envp) {
+ if ((sptr = index(envp, ';')) != 0)
+ *sptr = '\0';
+ if (strlen(envp) > 0) {
+ fqn_prefix[SYSCONFPREFIX] =
+ (char *) alloc(strlen(envp) + 10);
+ Strcpy(fqn_prefix[SYSCONFPREFIX], envp);
+ append_slash(fqn_prefix[SYSCONFPREFIX]);
+ Strcat(fqn_prefix[SYSCONFPREFIX], "NetHack\\");
+ }
+ }
+
+ /* okay so we have the overriding and definitive locaton
+ for sysconf, but only in the event that there is not a
+ sysconf file there (for whatever reason), check a secondary
+ location rather than abort. */
+
+ /* Is there a SYSCF_FILE there? */
+ fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
+ if (fd >= 0) {
+ /* readable */
+ close(fd);
+ have_syscf = TRUE;
+ }
+
+ if (!have_syscf) {
+ /* No SYSCF_FILE where there should be one, and
+ without an installer, a user may not be able
+ to place one there. So, let's try somewhere else... */
+ fqn_prefix[SYSCONFPREFIX] = fqn_prefix[0];
+
+ /* Is there a SYSCF_FILE there? */
+ fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
+ if (fd >= 0) {
+ /* readable */
+ close(fd);
+ have_syscf = TRUE;
+ }
+ }
+
+ /* user's home directory should default to this - unless
+ * overridden */
+ envp = nh_getenv("USERPROFILE");
+ if (envp) {
+ if ((sptr = index(envp, ';')) != 0)
+ *sptr = '\0';
+ if (strlen(envp) > 0) {
+ fqn_prefix[CONFIGPREFIX] =
+ (char *) alloc(strlen(envp) + 2);
+ Strcpy(fqn_prefix[CONFIGPREFIX], envp);
+ append_slash(fqn_prefix[CONFIGPREFIX]);
+ }
+ }
+ }
+ save_getreturn_status = getreturn_enabled;
+ getreturn_enabled = TRUE;
+ check_recordfile((char *) 0);
+ initoptions();
+ if (!validate_prefix_locations(failbuf)) {
+ raw_printf("Some invalid directory locations were specified:\n\t%s\n",
+ failbuf);
+ nethack_exit(EXIT_FAILURE);
+ }
+ if (!hackdir[0])
+ Strcpy(hackdir, orgdir);
+ if (argc > 1) {
+ if (argcheck(argc, argv, ARG_VERSION) == 2)
+ nethack_exit(EXIT_SUCCESS);
+
+ if (argcheck(argc, argv, ARG_DEBUG) == 1) {
+ argc--;
+ argv++;
+ }
+ if (argcheck(argc, argv, ARG_WINDOWS) == 1) {
+ argc--;
+ argv++;
+ }
+ if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
+ /* avoid matching "-dec" for DECgraphics; since the man page
+ * says -d directory, hope nobody's using -desomething_else
+ */
+ argc--;
+ argv++;
+ dir = argv[0] + 2;
+ if (*dir == '=' || *dir == ':')
+ dir++;
+ if (!*dir && argc > 1) {
+ argc--;
+ argv++;
+ dir = argv[0];
+ }
+ if (!*dir)
+ error("Flag -d must be followed by a directory name.");
+ Strcpy(hackdir, dir);
+ }
+ if (argc > 1) {
+#if !defined(TTY_GRAPHICS)
+ int sfd = 0;
+ boolean tmpconsole = FALSE;
+ hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+#endif
+ /*
+ * Now we know the directory containing 'record' and
+ * may do a prscore().
+ */
+ if (!strncmp(argv[1], "-s", 2)) {
+#if !defined(TTY_GRAPHICS)
+ /*
+ * Check to see if we're redirecting to a file.
+ */
+ sfd = (int) _fileno(stdout);
+ redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0;
+
+ if (!redirect_stdout && !hStdOut) {
+ raw_printf(
+ "-s is not supported for the Graphical Interface\n");
+ nethack_exit(EXIT_SUCCESS);
+ }
+#endif
+#ifdef SYSCF
+ initoptions();
+#endif
+ prscore(argc, argv);
+
+#if !defined(TTY_GRAPHICS)
+ if (tmpconsole) {
+ getreturn("to exit");
+ freefakeconsole();
+ tmpconsole = FALSE;
+ }
+#endif
+ nethack_exit(EXIT_SUCCESS);
+ }
+
+#if defined(MSWIN_GRAPHICS)
+ if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */
+ mswin_destroy_reg();
+ nethack_exit(EXIT_SUCCESS);
+ }
+#endif
+ /* Don't initialize the window system just to print usage */
+ if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
+ nhusage();
+
+#if !defined(TTY_GRAPHICS)
+ if (tmpconsole) {
+ getreturn("to exit");
+ freefakeconsole();
+ tmpconsole = FALSE;
+ }
+#endif
+ nethack_exit(EXIT_SUCCESS);
+ }
+ }
+ }
+ getreturn_enabled = save_getreturn_status;
+
+/*
+ * It seems you really want to play.
+ */
+ /* In 3.6.0, several ports process options before they init
+ * the window port. This allows settings that impact window
+ * ports to be specified or read from the sys or user config files.
+ */
+ process_options(argc, argv);
+
+ if (argc >= 1
+ && !strcmpi(default_window_sys, "mswin")
+ && strstri(argv[0], "nethackw.exe"))
+ iflags.windowtype_locked = TRUE;
+
+#if defined(TTY_GRAPHICS)
+ if (!iflags.windowtype_locked)
+ Strcpy(default_window_sys, "tty");
+#else
+#if defined(CURSES_GRAPHICS)
+ if (!iflags.windowtype_locked)
+ Strcpy(default_window_sys, "curses");
+#endif
+#endif
+ choose_windows(default_window_sys);
+ if (!dlb_init()) {
+ pline(
+ "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file "
+ "\"%s\".%s",
+ copyright_banner_line(1), copyright_banner_line(2),
+ copyright_banner_line(3), copyright_banner_line(4), DLBFILE,
+ "\nAre you perhaps trying to run NetHack within a zip utility?");
+ error("dlb_init failure.");
+ }
+
+ u.uhp = 1; /* prevent RIP on early quits */
+ u.ux = 0; /* prevent flush_screen() */
+
+ nethack_enter(argc, argv);
+ iflags.use_background_glyph = FALSE;
+ if (WINDOWPORT("mswin"))
+ iflags.use_background_glyph = TRUE;
+ if (WINDOWPORT("tty"))
+ nttty_open(1);
+
+ init_nhwindows(&argc, argv);
+
+ if (WINDOWPORT("tty"))
+ toggle_mouse_support();
+
+ /* strip role,race,&c suffix; calls askname() if plname[] is empty
+ or holds a generic user name like "player" or "games" */
+ plnamesuffix();
+ set_playmode(); /* sets plname to "wizard" for wizard mode */
+ /* until the getlock code is resolved, override askname()'s
+ setting of renameallowed; when False, player_selection()
+ won't resent renaming as an option */
+ iflags.renameallowed = FALSE;
+ /* Obtain the name of the logged on user and incorporate
+ * it into the name. */
+ Sprintf(fnamebuf, "%s-%s", get_username(0), plname);
+ (void) fname_encode(
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%',
+ fnamebuf, encodedfnamebuf, BUFSZ);
+ Sprintf(lock, "%s", encodedfnamebuf);
+ /* regularize(lock); */ /* we encode now, rather than substitute */
+ getlock();
+
+ /* Set up level 0 file to keep the game state.
+ */
+ fd = create_levelfile(0, (char *) 0);
+ if (fd < 0) {
+ raw_print("Cannot create lock file");
+ } else {
+ hackpid = GetCurrentProcessId();
+ write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
+ nhclose(fd);
+ }
+ /*
+ * Initialize the vision system. This must be before mklev() on a
+ * new game or before a level restore on a saved game.
+ */
+ vision_init();
+ display_gamewindows();
+ getreturn_enabled = TRUE;
+ /*
+ * First, try to find and restore a save file for specified character.
+ * We'll return here if new game player_selection() renames the hero.
+ */
+attempt_restore:
+ if ((fd = restore_saved_game()) >= 0) {
+#ifdef NEWS
+ if (iflags.news) {
+ display_file(NEWS, FALSE);
+ iflags.news = FALSE;
+ }
+#endif
+ pline("Restoring save file...");
+ mark_synch(); /* flush output */
+ if (dorecover(fd)) {
+ resuming = TRUE; /* not starting new game */
+ if (discover)
+ You("are in non-scoring discovery mode.");
+ if (discover || wizard) {
+ if (yn("Do you want to keep the save file?") == 'n')
+ (void) delete_savefile();
+ else {
+ nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
+ }
+ }
+ }
+ }
+
+ if (!resuming) {
+ /* new game: start by choosing role, race, etc;
+ player might change the hero's name while doing that,
+ in which case we try to restore under the new name
+ and skip selection this time if that didn't succeed */
+ if (!iflags.renameinprogress) {
+ player_selection();
+ if (iflags.renameinprogress) {
+ /* player has renamed the hero while selecting role;
+ discard current lock file and create another for
+ the new character name */
+ goto attempt_restore;
+ }
+ }
+ newgame();
+ if (discover)
+ You("are in non-scoring discovery mode.");
+ }
+ moveloop(resuming);
+ nethack_exit(EXIT_SUCCESS);
+ /*NOTREACHED*/
+ return 0;
+}
+
+STATIC_OVL void
+process_options(argc, argv)
+int argc;
+char *argv[];
+{
+ int i;
+
+ /*
+ * Process options.
+ */
+ while (argc > 1 && argv[1][0] == '-') {
+ argv++;
+ argc--;
+ switch (argv[0][1]) {
+ case 'a':
+ if (argv[0][2]) {
+ if ((i = str2align(&argv[0][2])) >= 0)
+ flags.initalign = i;
+ } else if (argc > 1) {
+ argc--;
+ argv++;
+ if ((i = str2align(argv[0])) >= 0)
+ flags.initalign = i;
+ }
+ break;
+ case 'D':
+ wizard = TRUE, discover = FALSE;
+ break;
+ case 'X':
+ discover = TRUE, wizard = FALSE;
+ break;
+#ifdef NEWS
+ case 'n':
+ iflags.news = FALSE;
+ break;
+#endif
+ case 'u':
+ if (argv[0][2])
+ (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
+ else if (argc > 1) {
+ argc--;
+ argv++;
+ (void) strncpy(plname, argv[0], sizeof(plname) - 1);
+ } else
+ raw_print("Player name expected after -u");
+ break;
+ case 'g':
+ if (argv[0][2]) {
+ if ((i = str2gend(&argv[0][2])) >= 0)
+ flags.initgend = i;
+ } else if (argc > 1) {
+ argc--;
+ argv++;
+ if ((i = str2gend(argv[0])) >= 0)
+ flags.initgend = i;
+ }
+ break;
+ case 'p': /* profession (role) */
+ if (argv[0][2]) {
+ if ((i = str2role(&argv[0][2])) >= 0)
+ flags.initrole = i;
+ } else if (argc > 1) {
+ argc--;
+ argv++;
+ if ((i = str2role(argv[0])) >= 0)
+ flags.initrole = i;
+ }
+ break;
+ case 'r': /* race */
+ if (argv[0][2]) {
+ if ((i = str2race(&argv[0][2])) >= 0)
+ flags.initrace = i;
+ } else if (argc > 1) {
+ argc--;
+ argv++;
+ if ((i = str2race(argv[0])) >= 0)
+ flags.initrace = i;
+ }
+ break;
+#if 0
+ case 'w': /* windowtype */
+#if defined(TTY_GRAPHICS)
+ if (!strncmpi(&argv[0][2], "tty", 3)) {
+ nttty_open(1);
+ }
+#endif
+ config_error_init(FALSE, "command line", FALSE);
+ choose_windows(&argv[0][2]);
+ config_error_done();
+ break;
+#endif
+ case '@':
+ flags.randomall = 1;
+ break;
+ default:
+ if ((i = str2role(&argv[0][1])) >= 0) {
+ flags.initrole = i;
+ break;
+ } else
+ raw_printf("\nUnknown switch: %s", argv[0]);
+ /* FALL THROUGH */
+ case '?':
+ nhusage();
+ nethack_exit(EXIT_SUCCESS);
+ }
+ }
+}
+
+STATIC_OVL void
+nhusage()
+{
+ char buf1[BUFSZ], buf2[BUFSZ], *bufptr;
+
+ buf1[0] = '\0';
+ bufptr = buf1;
+
+#define ADD_USAGE(s) \
+ if ((strlen(buf1) + strlen(s)) < (BUFSZ - 1)) \
+ Strcat(bufptr, s);
+
+ /* -role still works for those cases which aren't already taken, but
+ * is deprecated and will not be listed here.
+ */
+ (void) Sprintf(buf2, "\nUsage:\n%s [-d dir] -s [-r race] [-p profession] "
+ "[maxrank] [name]...\n or",
+ hname);
+ ADD_USAGE(buf2);
+
+ (void) Sprintf(
+ buf2, "\n%s [-d dir] [-u name] [-r race] [-p profession] [-[DX]]",
+ hname);
+ ADD_USAGE(buf2);
+#ifdef NEWS
+ ADD_USAGE(" [-n]");
+#endif
+ if (!iflags.window_inited)
+ raw_printf("%s\n", buf1);
+ else
+ (void) printf("%s\n", buf1);
+#undef ADD_USAGE
+}
+
+#ifdef PORT_HELP
+void
+port_help()
+{
+ /* display port specific help file */
+ display_file(PORT_HELP, 1);
+}
+#endif /* PORT_HELP */
+
+/* validate wizard mode if player has requested access to it */
+boolean
+authorize_wizard_mode()
+{
+ if (!strcmp(plname, WIZARD_NAME))
+ return TRUE;
+ return FALSE;
+}
+
+#define PATH_SEPARATOR '\\'
+
+#if defined(WIN32) && !defined(WIN32CON)
+static char exenamebuf[PATHLEN];
+extern HANDLE hConIn;
+extern HANDLE hConOut;
+boolean has_fakeconsole;
+
+char *
+exename()
+{
+ int bsize = PATHLEN;
+ char *tmp = exenamebuf, *tmp2;
+
+#ifdef UNICODE
+ {
+ TCHAR wbuf[PATHLEN * 4];
+ GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4);
+ WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
+ }
+#else
+ *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
+#endif
+ tmp2 = strrchr(tmp, PATH_SEPARATOR);
+ if (tmp2)
+ *tmp2 = '\0';
+ tmp2++;
+ return tmp2;
+}
+
+boolean
+fakeconsole(void)
+{
+ if (!hStdOut) {
+ HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (!hStdOut && !hStdIn) {
+ /* Bool rval; */
+ AllocConsole();
+ AttachConsole(GetCurrentProcessId());
+ /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
+ freopen("CON", "w", stdout);
+ freopen("CON", "r", stdin);
+ }
+ has_fakeconsole = TRUE;
+ }
+
+ /* Obtain handles for the standard Console I/O devices */
+ hConIn = GetStdHandle(STD_INPUT_HANDLE);
+ hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
+#if 0
+ if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
+ /* Unable to set control handler */
+ cmode = 0; /* just to have a statement to break on for debugger */
+ }
+#endif
+ return has_fakeconsole;
+}
+void freefakeconsole()
+{
+ if (has_fakeconsole) {
+ FreeConsole();
+ }
+}
+#endif
+
+#define EXEPATHBUFSZ 256
+char exepathbuf[EXEPATHBUFSZ];
+
+char *
+exepath(str)
+char *str;
+{
+ char *tmp, *tmp2;
+ int bsize;
+
+ if (!str)
+ return (char *) 0;
+ bsize = EXEPATHBUFSZ;
+ tmp = exepathbuf;
+#ifdef UNICODE
+ {
+ TCHAR wbuf[BUFSZ];
+ GetModuleFileName((HANDLE) 0, wbuf, BUFSZ);
+ WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
+ }
+#else
+ *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
+#endif
+ tmp2 = strrchr(tmp, PATH_SEPARATOR);
+ if (tmp2)
+ *tmp2 = '\0';
+ return tmp;
+}
+
+/*ARGSUSED*/
+void
+windows_raw_print(str)
+const char *str;
+{
+ if (str)
+ fprintf(stdout, "%s\n", str);
+ windows_nhgetch();
+ return;
+}
+
+/*ARGSUSED*/
+void
+windows_raw_print_bold(str)
+const char *str;
+{
+ windows_raw_print(str);
+ return;
+}
+
+int
+windows_nhgetch()
+{
+ return getchar();
+}
+
+
+void
+windows_nhbell()
+{
+ return;
+}
+
+/*ARGSUSED*/
+int
+windows_nh_poskey(x, y, mod)
+int *x, *y, *mod;
+{
+ return '\033';
+}
+
+/*ARGSUSED*/
+char
+windows_yn_function(query, resp, def)
+const char *query;
+const char *resp;
+char def;
+{
+ return '\033';
+}
+
+/*ARGSUSED*/
+static void
+windows_getlin(prompt, outbuf)
+const char *prompt UNUSED;
+char *outbuf;
+{
+ Strcpy(outbuf, "\033");
+}
+
+/*pcmain.c*/
typedef HWND(WINAPI *GETCONSOLEWINDOW)();
static HWND GetConsoleHandle(void);
static HWND GetConsoleHwnd(void);
+#if !defined(TTY_GRAPHICS)
+extern void NDECL(backsp);
+#endif
/* The function pointer nt_kbhit contains a kbhit() equivalent
* which varies depending on which window port is active.
<ClCompile Include="$(SrcDir)zap.c" />\r
<ClCompile Include="$(SysShareDir)cppregex.cpp" />\r
<ClCompile Include="$(SysShareDir)nhlan.c" />\r
- <ClCompile Include="$(SysShareDir)pcmain.c" />\r
<ClCompile Include="$(SysShareDir)pcsys.c" />\r
<ClCompile Include="$(SysShareDir)pcunix.c" />\r
<ClCompile Include="$(SysShareDir)random.c" />\r
+ <ClCompile Include="$(SysShareDir)safeproc.c" />\r
<ClCompile Include="$(SysWinntDir)ntsound.c" />\r
<ClCompile Include="$(SysWinntDir)nttty.c" />\r
<ClCompile Include="$(SysWinntDir)stubs.c">\r
<PreprocessorDefinitions>GUISTUB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ClCompile>\r
+ <ClCompile Include="$(SysWinntDir)windmain.c" />\r
<ClCompile Include="$(SysWinntDir)winnt.c" />\r
<ClCompile Include="$(WinTtyDir)getline.c" />\r
<ClCompile Include="$(WinTtyDir)topl.c" />\r
<Target Name="AfterRebuild">\r
<MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />\r
</Target>\r
-</Project>
\ No newline at end of file
+</Project>\r
<ClCompile Include="$(SrcDir)zap.c" />\r
<ClCompile Include="$(SysShareDir)cppregex.cpp" />\r
<ClCompile Include="$(SysShareDir)nhlan.c" />\r
- <ClCompile Include="$(SysShareDir)pcmain.c" />\r
<ClCompile Include="$(SysShareDir)pcsys.c" />\r
<ClCompile Include="$(SysShareDir)pcunix.c" />\r
<ClCompile Include="$(SysShareDir)random.c" />\r
+ <ClCompile Include="$(SysShareDir)safeproc.c" />\r
<ClCompile Include="$(SysWinntDir)ntsound.c" />\r
<ClCompile Include="$(SysWinntDir)stubs.c">\r
<PreprocessorDefinitions>TTYSTUB;</PreprocessorDefinitions>\r
</ClCompile>\r
+ <ClCompile Include="$(SysWinntDir)windmain.c" />\r
<ClCompile Include="$(SysWinntDir)winnt.c" />\r
<ClCompile Include="$(SysWinntDir)win10.c" />\r
<ClCompile Include="$(WinWin32Dir)mhaskyn.c" />\r
<Target Name="AfterRebuild">\r
<MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />\r
</Target>\r
-</Project>
\ No newline at end of file
+</Project>\r
#include "mhmain.h"
#include "mhmap.h"
+#if !defined(SAFEPROCS)
+#error You must #define SAFEPROCS to build winhack.c
+#endif
+
/* Borland and MinGW redefine "boolean" in shlwapi.h,
so just use the little bit we need */
typedef struct _DLLVERSIONINFO {
#endif
// Foward declarations of functions included in this code module:
-extern boolean FDECL(pcmain, (int, char **));
+extern boolean FDECL(main, (int, char **));
static void __cdecl mswin_moveloop(void *);
#define MAX_CMDLINE_PARAM 255
TCHAR *p;
TCHAR wbuf[BUFSZ];
char buf[BUFSZ];
+
DWORD major, minor;
- boolean resuming;
/* OSVERSIONINFO osvi; */
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
- /* We must initialize state sufficiently to support calls to panic */
+ /*
+ * Get a set of valid safe windowport function
+ * pointers during early startup initialization.
+ *
+ * When get_safe_procs is called with 0 as the param,
+ * non-functional, but safe function pointers are set
+ * for all windowport routines.
+ *
+ * When get_safe_procs is called with 1 as the param,
+ * raw_print, raw_print_bold, and wait_synch, and nhgetch
+ * are set to use C stdio routines via stdio_raw_print,
+ * stdio_raw_print_bold, stdio_wait_synch, and
+ * stdio_nhgetch.
+ */
+ windowprocs = *get_safe_procs(0);
+
+ /*
+ * Now we are going to override a couple
+ * of the windowprocs functions so that
+ * error messages are handled in a suitable
+ * way for the graphical version.
+ */
windowprocs.win_raw_print = mswin_raw_print;
windowprocs.win_raw_print_bold = mswin_raw_print_bold;
windowprocs.win_wait_synch = mswin_wait_synch;
win10_init();
-
sys_early_init();
- /* init applicatio structure */
+ /* init application structure */
_nethack_app.hApp = hInstance;
_nethack_app.hAccelTable =
LoadAccelerators(hInstance, (LPCTSTR) IDC_NETHACKW);
}
free(savefile);
}
- resuming = pcmain(argc, argv);
-
- moveloop(resuming);
+ /* let main do the argument processing */
+ (void) main(argc, argv);
return 0;
}