diff --git a/include/decl.h b/include/decl.h
index f66c0f5a8..a34550ef9 100644
--- a/include/decl.h
+++ b/include/decl.h
@@ -725,8 +725,7 @@ struct instance_globals_o {
/* options.c */
- /* builtin_opt, syscf_, rc_file_, environ_, play_opt */
- enum option_phases opt_phase;
+ int opt_phase; /* builtin_opt, syscf_, rc_file_, environ_, play_opt */
boolean opt_initial;
boolean opt_from_file;
boolean opt_need_redraw; /* for doset() */
diff --git a/include/extern.h b/include/extern.h
index b3206b015..8ed1b0f0f 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -335,8 +335,6 @@ extern boolean parse_conf_file(FILE *fp, boolean (*proc)(char *arg));
extern void set_configfile_name(const char *);
extern char *get_configfile(void);
extern const char *get_default_configfile(void);
-extern void rcfile(void);
-extern void rcfile_interface_options(void);
/* ### coloratt.c ### */
@@ -2322,10 +2320,6 @@ extern int msgtype_type(const char *, boolean) NONNULLARG1;
extern void hide_unhide_msgtypes(boolean, int);
extern void msgtype_free(void);
extern void options_free_window_colors(void);
-extern void set_all_options_heeded(void);
-extern void set_all_options_disregarded(void);
-extern void heed_this_option(enum opt);
-extern void disregard_this_option(enum opt);
#ifdef TTY_PERM_INVENT
extern void check_perm_invent_again(void);
#endif
@@ -2351,7 +2345,6 @@ extern int dowhatdoes(void);
extern char *dowhatdoes_core(char, char *) NONNULLARG2; /*might return NULL*/
extern int dohelp(void);
extern int dohistory(void);
-void allopt_array_init(void);
/* ### xxmain.c ### */
diff --git a/include/global.h b/include/global.h
index 1439044f1..21b00fe46 100644
--- a/include/global.h
+++ b/include/global.h
@@ -102,6 +102,8 @@ typedef unsigned readLenType;
#endif
#define BOOL_RANDOM (-1)
+enum optchoice { opt_in, opt_out};
+
/*
* type nhsym: loadable symbols go into this type
*/
@@ -151,16 +153,6 @@ typedef uchar nhsym;
#endif /* __GNUC__ || _MSC_VER */
#endif /* !__clang__ */
-#define SET__IS_VALUE_VALID(s) ((s < set_in_sysconf) || (s > set_wiznofuz))
-#include "optlist.h"
-enum opt {
- opt_prefix_only = -1,
-#define NHOPT_ENUM
-#include "optlist.h"
-#undef NHOPT_ENUM
- OPTCOUNT
-};
-
/*
* Automatic inclusions for the subsidiary files.
* Please don't change the order. It does matter.
diff --git a/include/hack.h b/include/hack.h
index f655a8961..bb9f9d642 100644
--- a/include/hack.h
+++ b/include/hack.h
@@ -702,6 +702,22 @@ enum nhcb_calls {
NUM_NHCB
};
+/*
+ * option setting restrictions
+ */
+
+enum optset_restrictions {
+ set_in_sysconf = 0, /* system config file option only */
+ set_in_config = 1, /* config file option only */
+ set_viaprog = 2, /* may be set via extern program, not seen in game */
+ set_gameview = 3, /* may be set via extern program, displayed in game */
+ set_in_game = 4, /* may be set via extern program or set in the game */
+ set_wizonly = 5, /* may be set in the game if wizmode */
+ set_wiznofuz = 6, /* wizard-mode only, but not by fuzzer */
+ set_hidden = 7 /* placeholder for prefixed entries, never show it */
+};
+#define SET__IS_VALUE_VALID(s) ((s < set_in_sysconf) || (s > set_wiznofuz))
+
struct plinemsg_type {
xint16 msgtype; /* one of MSGTYP_foo */
struct nhregex *regex;
diff --git a/include/optlist.h b/include/optlist.h
index 9322bee7e..b920048ac 100644
--- a/include/optlist.h
+++ b/include/optlist.h
@@ -4,6 +4,10 @@
#ifndef OPTLIST_H
#define OPTLIST_H
+#ifdef OPTIONS_C
+static int optfn_boolean(int, int, boolean, char *, char *);
+#endif
+
/*
* NOTE: If you add (or delete) an option, please review:
* doc/options.txt
@@ -12,37 +16,6 @@
* updates that should accompany your change.
*/
-#define BACKWARD_COMPAT
-
-extern int optfn_boolean(int, int, boolean, char *, char *);
-enum optchoice { opt_in, opt_out };
-
-/*
- * option setting restrictions
- */
-enum optset_restrictions {
- set_in_sysconf = 0, /* system config file option only */
- set_in_config = 1, /* config file option only */
- set_viaprog = 2, /* may be set via extern program, not seen in game */
- set_gameview = 3, /* may be set via extern program, displayed in game */
- set_in_game = 4, /* may be set via extern program or set in the game */
- set_wizonly = 5, /* may be set in the game if wizmode */
- set_wiznofuz = 6, /* wizard-mode only, but not by fuzzer */
- set_hidden = 7 /* placeholder for prefixed entries, never show it */
-};
-
-/* these aren't the same as set_xxx */
-enum option_phases {
- phase_not_set = 0,
- builtin_opt = 1, /* compiled-in default value of an option */
- syscf_opt, /* sysconf setting of an option, overrides builtin */
- rc_file_opt, /* player's run-time config file setting, overrides syscf */
- environ_opt, /* player's environment NETHACKOPTIONS, overrides rc_file */
- cmdline_opt, /* program invocation command-line, overrides environ */
- play_opt, /* 'O' command, interactively set so overrides all */
- num_opt_phases
-};
-
enum OptType { BoolOpt, CompOpt, OthrOpt };
enum Y_N { No, Yes };
enum Off_On { Off, On };
@@ -72,7 +45,7 @@ struct allopt_t {
const char *alias;
const char *descr;
const char *prefixgw;
- boolean initval, has_handler, dupdetected, disregarded;
+ boolean initval, has_handler, dupdetected;
};
#endif /* OPTLIST_H */
@@ -101,16 +74,16 @@ static int optfn_##a(int, int, boolean, char *, char *);
#elif defined(NHOPT_PARSE)
#define NHOPTB(a, sec, b, c, s, i, n, v, d, al, bp, termp, desc) \
{ #a, OptS_##sec, 0, b, opt_##a, s, BoolOpt, n, v, d, No, termp, c, \
- bp, &optfn_boolean, al, desc, (const char *) 0, i, 0, 0 , 0 },
+ bp, &optfn_boolean, al, desc, (const char *) 0, i, 0, 0 },
#define NHOPTC(a, sec, b, c, s, n, v, d, h, al, z) \
{ #a, OptS_##sec, 0, b, opt_##a, s, CompOpt, n, v, d, No, 0, c, \
- (boolean *) 0, &optfn_##a, al, z, (const char *) 0, Off, h, 0, 0 },
+ (boolean *) 0, &optfn_##a, al, z, (const char *) 0, Off, h, 0 },
#define NHOPTP(a, sec, b, c, s, n, v, d, h, al, z) \
{ #a, OptS_##sec, 0, b, pfx_##a, s, CompOpt, n, v, d, Yes, 0, c, \
- (boolean *) 0, &pfxfn_##a, al, z, #a, Off, h, 0, 0 },
+ (boolean *) 0, &pfxfn_##a, al, z, #a, Off, h, 0 },
#define NHOPTO(m, sec, a, b, c, s, n, v, d, al, z) \
{ m, OptS_##sec, 0, b, opt_##a, s, OthrOpt, n, v, d, No, 0, c, \
- (boolean *) 0, &optfn_##a, al, z, (const char *) 0, On, On, 0, 0 },
+ (boolean *) 0, &optfn_##a, al, z, (const char *) 0, On, On, 0 },
/* this is not reliable because TILES_IN_GLYPHMAP might be defined
* in a multi-interface binary but not apply to the current interface */
diff --git a/include/windconf.h b/include/windconf.h
index b7330668c..bd30f8a6b 100644
--- a/include/windconf.h
+++ b/include/windconf.h
@@ -32,8 +32,6 @@
#define OPTIONS_AT_RUNTIME /* build info done at runtime not text file */
-#define EARLY_CONFIGFILE_PASS
-
/*
* -----------------------------------------------------------------
* The remaining code shouldn't need modification.
diff --git a/include/winprocs.h b/include/winprocs.h
index 014ee1e09..688d76138 100644
--- a/include/winprocs.h
+++ b/include/winprocs.h
@@ -415,4 +415,79 @@ struct chain_procs {
};
#endif /* WINCHAIN */
+#ifdef SAFEPROCS
+/*
+ * window port routines available in sys/share/safeproc.c
+ */
+extern struct window_procs *get_safe_procs(int);
+extern void safe_init_nhwindows(int *, char **);
+extern void safe_player_selection(void);
+extern void safe_askname(void);
+extern void safe_get_nh_event(void);
+extern void safe_exit_nhwindows(const char *);
+extern void safe_suspend_nhwindows(const char *);
+extern void safe_resume_nhwindows(void);
+extern winid safe_create_nhwindow(int);
+extern void safe_clear_nhwindow(winid);
+extern void safe_display_nhwindow(winid, boolean);
+extern void safe_destroy_nhwindow(winid);
+extern void safe_curs(winid, int, int);
+extern void safe_putstr(winid, int, const char *);
+extern void safe_putmixed(winid, int, const char *);
+extern void safe_display_file(const char *, boolean);
+extern void safe_start_menu(winid, unsigned long);
+extern void safe_add_menu(winid, const glyph_info *, const ANY_P *,
+ char, char, int, int, const char *,
+ unsigned int);
+extern void safe_end_menu(winid, const char *);
+extern int safe_select_menu(winid, int, MENU_ITEM_P **);
+extern char safe_message_menu(char, int, const char *);
+extern void safe_mark_synch(void);
+extern void safe_wait_synch(void);
+#ifdef CLIPPING
+extern void safe_cliparound(int, int);
+#endif
+#ifdef POSITIONBAR
+extern void safe_update_positionbar(char *);
+#endif
+extern void safe_print_glyph(winid, coordxy, coordxy,
+ const glyph_info *, const glyph_info *);
+extern void safe_raw_print(const char *);
+extern void safe_raw_print_bold(const char *);
+extern int safe_nhgetch(void);
+extern int safe_nh_poskey(coordxy *, coordxy *, int *);
+extern void safe_nhbell(void);
+extern int safe_doprev_message(void);
+extern char safe_yn_function(const char *, const char *, char);
+extern void safe_getlin(const char *, char *);
+extern int safe_get_ext_cmd(void);
+extern void safe_number_pad(int);
+extern void safe_delay_output(void);
+#ifdef CHANGE_COLOR
+extern void safe_change_color(int, long, int);
+#ifdef MAC
+extern void safe_change_background(int);
+extern short safe_set_font_name(winid, char *);
+#endif
+extern char *safe_get_color_string(void);
+#endif
+extern void safe_outrip(winid, int, time_t);
+extern void safe_preference_update(const char *);
+extern char *safe_getmsghistory(boolean);
+extern void safe_putmsghistory(const char *, boolean);
+extern void safe_status_init(void);
+extern void safe_status_finish(void);
+extern void safe_status_enablefield(int, const char *, const char *,
+ boolean);
+extern void safe_status_update(int, genericptr_t, int, int, int,
+ unsigned long *);
+extern boolean safe_can_suspend(void);
+extern void stdio_raw_print(const char *);
+extern void stdio_nonl_raw_print(const char *);
+extern void stdio_raw_print_bold(const char *);
+extern void stdio_wait_synch(void);
+extern void safe_update_inventory(int);
+extern win_request_info *safe_ctrl_nhwindow(winid, int, win_request_info *);
+extern int stdio_nhgetch(void);
+#endif /* SAFEPROCS */
#endif /* WINPROCS_H */
diff --git a/src/cfgfiles.c b/src/cfgfiles.c
index 439747127..1b4715a4f 100644
--- a/src/cfgfiles.c
+++ b/src/cfgfiles.c
@@ -1881,85 +1881,6 @@ vconfig_error_add(const char *str, va_list the_args)
config_erradd(buf);
}
-void
-rcfile(void)
-{
- char *opts = 0, *xtraopts = 0;
- const char *envname, *namesrc, *nameval;
-
- go.opt_phase = environ_opt;
- /* getenv() instead of nhgetenv(): let total length of options be long;
- parseoptions() will check each individually */
- envname = "NETHACKOPTIONS";
- opts = getenv(envname);
- if (!opts) {
- /* fall back to original name; discouraged */
- envname = "HACKOPTIONS";
- opts = getenv(envname);
- }
-
- if (gc.cmdline_rcfile) {
- namesrc = "command line";
- nameval = gc.cmdline_rcfile;
- xtraopts = opts;
- if (opts && (*opts == '/' || *opts == '\\' || *opts == '@'))
- xtraopts = 0; /* NETHACKOPTIONS is a file name; ignore it */
- } else if (opts && (*opts == '/' || *opts == '\\' || *opts == '@')) {
- /* NETHACKOPTIONS is a file name; use that instead of the default */
- if (*opts == '@')
- ++opts; /* @filename */
- namesrc = envname;
- nameval = opts;
- xtraopts = 0;
- } else {
- /* either no NETHACKOPTIONS or it wasn't a file name;
- read the default configuration file */
- nameval = namesrc = 0;
- xtraopts = opts;
- }
-
- go.opt_phase = rc_file_opt;
- /* seemingly arbitrary name length restriction is to prevent error
- messages, if any were to be delivered while accessing the file,
- from potentially overflowing buffers */
- if (nameval && (int) strlen(nameval) >= BUFSZ / 2) {
- config_error_init(TRUE, namesrc, FALSE);
- config_error_add(
- "nethackrc file name \"%.40s\"... too long; using default",
- nameval);
- config_error_done();
- nameval = namesrc = 0; /* revert to default nethackrc */
- }
-
- config_error_init(TRUE, nameval, nameval ? CONFIG_ERROR_SECURE : FALSE);
- (void) read_config_file(nameval, set_in_config);
- config_error_done();
- if (xtraopts) {
- /* NETHACKOPTIONS is present and not a file name */
- go.opt_phase = environ_opt;
- config_error_init(FALSE, envname, FALSE);
- (void) parseoptions(xtraopts, TRUE, FALSE);
- config_error_done();
- }
-
- if (gc.cmdline_rcfile)
- free((genericptr_t) gc.cmdline_rcfile), gc.cmdline_rcfile = 0;
- /*[end of nethackrc handling]*/
-}
-
-void
-rcfile_interface_options(void)
-{
- allopt_array_init();
- set_all_options_disregarded();
- heed_this_option(opt_windowtype);
- heed_this_option(opt_soundlib);
- rcfile();
- set_all_options_heeded();
- disregard_this_option(opt_windowtype);
- disregard_this_option(opt_soundlib);
-}
-
#ifdef SYSCF
#ifdef SYSCF_FILE
void
diff --git a/src/decl.c b/src/decl.c
index f229de737..cc1e8a3b6 100644
--- a/src/decl.c
+++ b/src/decl.c
@@ -592,7 +592,7 @@ static const struct instance_globals_o g_init_o = {
/* o_init.c */
DUMMY, /* oclass_prob_totals */
/* options.c */
- phase_not_set, /* opt_phase */
+ 0, /* opt_phase */
FALSE, /* opt_initial */
FALSE, /* opt_from_file */
FALSE, /* opt_need_redraw */
diff --git a/src/options.c b/src/options.c
index 8bfe77d97..c22105c03 100644
--- a/src/options.c
+++ b/src/options.c
@@ -56,13 +56,21 @@ NEARDATA struct accessibility_data a11y;
#include "optlist.h"
#undef NHOPT_PROTO
+#define NHOPT_ENUM
+enum opt {
+ opt_prefix_only = -1,
+#include "optlist.h"
+ OPTCOUNT
+};
+#undef NHOPT_ENUM
+
#define NHOPT_PARSE
static struct allopt_t allopt_init[] = {
#include "optlist.h"
{(const char *) 0, OptS_Advanced, 0, 0, 0, set_in_sysconf, BoolOpt,
No, No, No, No, Term_False, 0, (boolean *) 0,
(int (*)(int, int, boolean, char *, char *)) 0,
- (char *) 0, (const char *) 0, (const char *) 0, 0, 0, 0, TRUE }
+ (char *) 0, (const char *) 0, (const char *) 0, 0, 0, 0 }
};
#undef NHOPT_PARSE
@@ -86,6 +94,16 @@ enum optn_result {
enum requests {
do_nothing, do_init, do_set, do_handler, get_val, get_cnf_val
};
+/* these aren't the same as set_xxx in optlist.h */
+enum option_phases {
+ builtin_opt=1,/* compiled-in default value of an option */
+ syscf_opt, /* sysconf setting of an option, overrides builtin */
+ rc_file_opt, /* player's run-time config file setting, overrides syscf */
+ environ_opt, /* player's environment NETHACKOPTIONS, overrides rc_file */
+ cmdline_opt, /* program invocation command-line, overrides environ */
+ play_opt, /* 'O' command, interactively set so overrides all */
+ num_opt_phases
+};
static struct allopt_t allopt[SIZE(allopt_init)];
@@ -106,7 +124,6 @@ extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
static char empty_optstr[] = { '\0' };
static boolean duplicate, using_alias;
static boolean give_opt_msg = TRUE;
-static boolean restricted_options_mode = FALSE;
enum { MAX_ROLEOPT = 4 }; /* 4: role,race,gend,algn */
static boolean opt_set_in_config[OPTCOUNT];
@@ -340,7 +357,6 @@ static const menu_cmd_t default_menu_cmd_info[] = {
static const char n_currently_set[] = "(%d currently set)";
-staticfn void allopt_array_init(void);
staticfn void nmcpy(char *, const char *, int);
staticfn void escapes(const char *, char *);
staticfn void rejectoption(const char *);
@@ -579,7 +595,7 @@ parseoptions(
* placed that number into each option's allopt[n].minmatch.
*
*/
- if (!got_match && allopt[i].name)
+ if (!got_match)
got_match = match_optname(opts, allopt[i].name,
allopt[i].minmatch, TRUE);
if (got_match) {
@@ -618,8 +634,7 @@ parseoptions(
/* allow optfn's to test whether they were called from parseoptions() */
program_state.in_parseoptions++;
- if (got_match && (matchidx >= 0 && matchidx < OPTCOUNT)
- && !allopt[matchidx].disregarded) {
+ if (got_match && matchidx >= 0) {
duplicate = duplicate_opt_detection(matchidx);
if (duplicate && !allopt[matchidx].dupeok)
complain_about_duplicate(matchidx);
@@ -669,7 +684,7 @@ parseoptions(
}
}
- if (optresult == optn_silenterr || restricted_options_mode)
+ if (optresult == optn_silenterr)
return FALSE;
if (pfx_match && optresult == optn_err) {
char pfxbuf[BUFSZ], *pfxp;
@@ -4956,20 +4971,17 @@ optfn_windowtype(
* _end_ because comma-separated option strings are processed from
* right to left.
*/
- if (!iflags.window_inited) {
- if (iflags.windowtype_locked)
- return optn_ok;
+ if (iflags.windowtype_locked)
+ return optn_ok;
- if ((op = string_for_env_opt(allopt[optidx].name, opts, FALSE))
- != empty_optstr) {
- nmcpy(gc.chosen_windowtype, op, WINTYPELEN);
- if (!iflags.windowtype_deferred) {
- choose_windows(gc.chosen_windowtype);
- }
- } else {
- return optn_err;
+ if ((op = string_for_env_opt(allopt[optidx].name, opts, FALSE))
+ != empty_optstr) {
+ nmcpy(gc.chosen_windowtype, op, WINTYPELEN);
+ if (!iflags.windowtype_deferred) {
+ choose_windows(gc.chosen_windowtype);
}
- }
+ } else
+ return optn_err;
return optn_ok;
}
if (req == get_val || req == get_cnf_val) {
@@ -7054,14 +7066,29 @@ txt2key(char *txt)
void
initoptions(void)
{
+ int i;
+
/*
* Most places that call initoptions_init()/initoptions() would
* have the calls next to each other, so instead of adding
* initoptions_init() everywhere, just add it where it's needed in
* a non-adjacent place and call it here for all the other cases.
*/
- if (go.opt_phase != builtin_opt)
+ if(go.opt_phase != builtin_opt)
initoptions_init();
+
+ /*
+ * Call each option function with an init flag and give it a chance
+ * to make any preparations that it might require. We do this
+ * whether or not the option itself is ever specified; that's
+ * irrelevant for the init call. Doing this allows the prep code for
+ * option settings to remain adjacent to, and in the same function as,
+ * the code that processes those options.
+ */
+ for (i = 0; i < OPTCOUNT; ++i) {
+ if (allopt[i].optfn)
+ (*allopt[i].optfn)(i, do_init, FALSE, empty_optstr, empty_optstr);
+ }
#ifdef SYSCF
/* someday there may be other SYSCF alternatives besides text file */
#ifdef SYSCF_FILE
@@ -7103,7 +7130,9 @@ initoptions_init(void)
go.opt_phase = builtin_opt; /* Did I need to move this here? */
/* initialize the function pointers for saving the game */
sf_init();
- allopt_array_init();
+ memcpy(allopt, allopt_init, sizeof(allopt));
+ determine_ambiguities();
+
/* if windowtype has been specified on the command line, set it up
early so windowtype-specific options use it as their base */
if (gc.cmdline_windowsys) {
@@ -7257,28 +7286,6 @@ initoptions_init(void)
/* since this is done before init_objects(), do partial init here */
objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
nmcpy(svp.pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
-
-#ifdef SYSCF
-/* someday there may be other SYSCF alternatives besides text file */
-#ifdef SYSCF_FILE
- /* If SYSCF_FILE is specified, it _must_ exist... */
- assure_syscf_file();
- config_error_init(TRUE, SYSCF_FILE, FALSE);
-
- /* ... and _must_ parse correctly. */
- go.opt_phase = syscf_opt;
- if (!read_config_file(SYSCF_FILE, set_in_sysconf)) {
- if (config_error_done() && !iflags.initoptions_noterminate)
- nh_terminate(EXIT_FAILURE);
- }
- config_error_done();
- /*
- * TODO [maybe]: parse the sysopt entries which are space-separated
- * lists of usernames into arrays with one name per element.
- */
-#endif
-#endif /* SYSCF */
- initoptions_finish();
}
/*
@@ -7299,69 +7306,72 @@ initoptions_init(void)
*/
void
initoptions_finish(void)
-{ nhsym sym = 0;
+{
+ nhsym sym = 0;
+ char *opts = 0, *xtraopts = 0;
+#ifndef MAC
+ const char *envname, *namesrc, *nameval;
- rcfile();
-
- (void) fruitadd(svp.pl_fruit, (struct fruit *) 0);
- /*
- * Remove "slime mold" from list of object names. This will
- * prevent it from being wished unless it's actually present
- * as a named (or default) fruit. Wishing for "fruit" will
- * result in the player's preferred fruit. [Once upon a time
- * the override value used was "\033" which prevented wishing
- * for the slime mold object at all except by asking for a
- * specific named fruit.] Note that there are multiple fruit
- * object types (apple, melon, &c) but the "fruit" object is
- * slime mold or whatever custom name player assigns to that.
- */
- obj_descr[SLIME_MOLD].oc_name = "fruit";
-
- sym = get_othersym(SYM_BOULDER,
- Is_rogue_level(&u.uz) ? ROGUESET : PRIMARYSET);
- if (sym)
- gs.showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
- reglyph_darkroom();
- reset_glyphmap(gm_optionchange);
-#ifdef STATUS_HILITES
- /*
- * 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 (!WINDOWPORT(safestartup)) {
- if (iflags.hilite_delta && !wc2_supported("statushilites")) {
- raw_printf("Status highlighting not supported for %s interface.",
- windowprocs.name);
- iflags.hilite_delta = 0;
- }
+ /* getenv() instead of nhgetenv(): let total length of options be long;
+ parseoptions() will check each individually */
+ envname = "NETHACKOPTIONS";
+ opts = getenv(envname);
+ if (!opts) {
+ /* fall back to original name; discouraged */
+ envname = "HACKOPTIONS";
+ opts = getenv(envname);
}
-#endif
- update_rest_on_space();
- /* these can't rely on compile-time initialization for their defaults
- because a multi-interface binary might need different values for
- different interfaces; if neither tiled_map nor ascii_map pass the
- wc_supported() test, assume ascii_map */
- if (iflags.wc_tiled_map && !wc_supported("tiled_map"))
- iflags.wc_tiled_map = FALSE, iflags.wc_ascii_map = TRUE;
- else if (iflags.wc_ascii_map && !wc_supported("ascii_map")
- && wc_supported("tiled_map"))
- iflags.wc_ascii_map = FALSE, iflags.wc_tiled_map = TRUE;
+ if (gc.cmdline_rcfile) {
+ namesrc = "command line";
+ nameval = gc.cmdline_rcfile;
+ xtraopts = opts;
+ if (opts && (*opts == '/' || *opts == '\\' || *opts == '@'))
+ xtraopts = 0; /* NETHACKOPTIONS is a file name; ignore it */
+ } else if (opts && (*opts == '/' || *opts == '\\' || *opts == '@')) {
+ /* NETHACKOPTIONS is a file name; use that instead of the default */
+ if (*opts == '@')
+ ++opts; /* @filename */
+ namesrc = envname;
+ nameval = opts;
+ xtraopts = 0;
+ } else
+#endif /* !MAC */
+ /*else*/ {
+ /* either no NETHACKOPTIONS or it wasn't a file name;
+ read the default configuration file */
+ nameval = namesrc = 0;
+ xtraopts = opts;
+ }
-#ifdef ENHANCED_SYMBOLS
- if (glyphid_cache_status())
- free_glyphid_cache();
- apply_customizations(gc.currentgraphics, do_custom_symbols);
-#endif
- go.opt_initial = FALSE;
- return;
-}
+ /* seemingly arbitrary name length restriction is to prevent error
+ messages, if any were to be delivered while accessing the file,
+ from potentially overflowing buffers */
+ if (nameval && (int) strlen(nameval) >= BUFSZ / 2) {
+ go.opt_phase = rc_file_opt;
+ config_error_init(TRUE, namesrc, FALSE);
+ config_error_add(
+ "nethackrc file name \"%.40s\"... too long; using default",
+ nameval);
+ config_error_done();
+ nameval = namesrc = 0; /* revert to default nethackrc */
+ }
+
+ config_error_init(TRUE, nameval, nameval ? CONFIG_ERROR_SECURE : FALSE);
+ (void) read_config_file(nameval, set_in_config);
+ config_error_done();
+ if (xtraopts) {
+ /* NETHACKOPTIONS is present and not a file name */
+ go.opt_phase = environ_opt;
+ config_error_init(FALSE, envname, FALSE);
+ (void) parseoptions(xtraopts, TRUE, FALSE);
+ config_error_done();
+ }
+
+ if (gc.cmdline_rcfile)
+ free((genericptr_t) gc.cmdline_rcfile), gc.cmdline_rcfile = 0;
+ /*[end of nethackrc handling]*/
-#if 0
(void) fruitadd(svp.pl_fruit, (struct fruit *) 0);
/*
* Remove "slime mold" from list of object names. This will
@@ -7439,37 +7449,6 @@ initoptions_finish(void)
}
return;
}
-#endif
-void
-allopt_array_init(void)
-{
- int i;
- static boolean options_array_inited_already = FALSE;
-
- if (!options_array_inited_already) {
- memcpy(allopt, allopt_init, sizeof(allopt));
- determine_ambiguities();
- for (i = 0; allopt[i].name; i++) {
- if (allopt[i].addr)
- *(allopt[i].addr) = allopt[i].initval;
- }
- set_all_options_heeded();
- /*
- * Call each option function with an init flag and give it a chance
- * to make any preparations that it might require. We do this
- * whether or not the option itself is ever specified; that's
- * irrelevant for the init call. Doing this allows the prep code for
- * option settings to remain adjacent to, and in the same function as,
- * the code that processes those options.
- */
- for (i = 0; i < OPTCOUNT; ++i) {
- if (allopt[i].optfn)
- (*allopt[i].optfn)(i, do_init, FALSE, empty_optstr,
- empty_optstr);
- }
- options_array_inited_already = TRUE;
- }
-}
/*
*******************************************
@@ -8987,7 +8966,6 @@ doset(void) /* changing options via menu by Per Liboriussen */
if (opt_indx < -1)
opt_indx++; /* -1 offset for select_menu() */
opt_indx -= indexoffset;
- assert(IndexOk(opt_indx, allopt));
if (allopt[opt_indx].opttyp == BoolOpt) {
/* boolean option */
Sprintf(buf, "%s%s", *allopt[opt_indx].addr ? "!" : "",
@@ -10242,41 +10220,6 @@ enhance_menu_text(
return;
}
-void
-set_all_options_heeded(void)
-{
- int i;
-
- for (i = 0; i < OPTCOUNT; i++)
- allopt[i].disregarded = FALSE;
- restricted_options_mode = FALSE;
-}
-
-void
-set_all_options_disregarded(void)
-{
- int i;
-
- for (i = 0; i < OPTCOUNT ; i++)
- allopt[i].disregarded = TRUE;
- restricted_options_mode = TRUE;
-}
-
-void
-heed_this_option(enum opt optidx)
-{
- if (optidx >= 0 && optidx < (enum opt) OPTCOUNT)
- allopt[optidx].disregarded = FALSE;
-}
-void
-disregard_this_option(enum opt optidx)
-{
- if (optidx >= 0 && optidx < (enum opt) OPTCOUNT)
- allopt[optidx].disregarded = TRUE;
- if (!restricted_options_mode)
- restricted_options_mode = TRUE;
-}
-
#undef OPTIONS_HEADING
#undef CONFIG_SLOT
diff --git a/sys/windows/GNUmakefile b/sys/windows/GNUmakefile
index 4bc3df970..3ea5c777b 100644
--- a/sys/windows/GNUmakefile
+++ b/sys/windows/GNUmakefile
@@ -1239,14 +1239,14 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl \
nhlobj nhlsel nhlua windsound o_init objects objnam options \
pager pickup pline polyself potion pray priest quest questpgr \
random read rect region report restore rip rnd role rumors \
- save sfbase sfstruct shk shknam sit selvar sounds sp_lev \
+ safeproc save sfbase sfstruct shk shknam sit selvar sounds sp_lev \
spell stairs steal steed strutil \
symbols sys teleport timeout topten track trap u_init uhitm utf8map \
vault version vision weapon were wield windmain windows windsys wizard \
wizcmds worm worn write zap $(SOUNDLIBOBJS))
-CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(SOUNDLIBINCL) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
-CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
+CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(SOUNDLIBINCL) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
+CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
ONHW = $(O)nethackw
NHWONLY = $(addsuffix .o, mhaskyn mhdlg mhfont mhinput mhmain mhmap mhmenu \
@@ -1348,8 +1348,8 @@ CLEAN_FILE += $(NHWTARGETS) $(NHWOBJS) $(NHWRES) $(BMPS) $(WAV)
#==========================================
# nethack
#==========================================
-CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) $(SOUNDLIBINCL) -DNO_TILE_C -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
-CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
+CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) $(SOUNDLIBINCL) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
+CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
ONH = $(O)nethack
diff --git a/sys/windows/Makefile.nmake b/sys/windows/Makefile.nmake
index fe481ecc2..2097d7183 100644
--- a/sys/windows/Makefile.nmake
+++ b/sys/windows/Makefile.nmake
@@ -847,7 +847,8 @@ REGEXTTY = $(OTTY)cppregex.o
LUAOBJTTY = $(OTTY)nhlua.o $(OTTY)nhlsel.o $(OTTY)nhlobj.o
VVOBJTTY = $(OTTY)version.o
-SOBJTTY = $(OTTY)windmain.o $(OTTY)windsys.o $(OTTY)win10.o
+SOBJTTY = $(OTTY)windmain.o $(OTTY)windsys.o $(OTTY)win10.o \
+ $(OTTY)safeproc.o
TTYOBJTTY = $(OTTY)topl.o $(OTTY)getline.o $(OTTY)wintty.o
@@ -907,7 +908,8 @@ REGEXGUI = $(OGUI)cppregex.o
LUAOBJGUI = $(OGUI)nhlua.o $(OGUI)nhlsel.o $(OGUI)nhlobj.o
VVOBJGUI = $(OGUI)version.o
-SOBJGUI = $(OGUI)windmain.o $(OGUI)windsys.o $(OGUI)win10.o
+SOBJGUI = $(OGUI)windmain.o $(OGUI)windsys.o $(OGUI)win10.o \
+ $(OGUI)safeproc.o
GUIOBJ = $(OGUI)mhaskyn.o $(OGUI)mhdlg.o \
$(OGUI)mhfont.o $(OGUI)mhinput.o $(OGUI)mhmain.o $(OGUI)mhmap.o \
@@ -1362,8 +1364,8 @@ INCLUSIONS= /I$(R_INCL) /I$(R_MSWSYS) $(R_LUAINCL) $(R_SOUNDLIBINCL)
# Util and console builds
#==========================================
-CFLAGS = $(ctmpflags) $(INCLUSIONS) $(DLBDEF) $(SOUNDLIBDEFS)
-CPPFLAGS = $(cpptmpflags) $(INCLUSIONS) $(DLBDEF) $(SOUNDLIBDEFS)
+CFLAGS = $(ctmpflags) $(INCLUSIONS) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
+CPPFLAGS = $(cpptmpflags) $(INCLUSIONS) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
LFLAGS = $(lflags) $(conlibs) $(MACHINE)
#==========================================
@@ -2388,12 +2390,14 @@ $(OTTY)windsys.o: $(MSWSYS)windsys.c $(WINDHDR) $(HACK_H)
$(OTTY)windsound.o: $(WINDSOUNDDIR)windsound.c $(HACK_H)
#$(OTTY)sample.o: $(SOUNDDIR)sample.c $(HACK_H)
$(OTTY)windmain.o: $(MSWSYS)windmain.c $(WINDHDR) $(HACK_H)
+$(OTTY)safeproc.o: $(WSHR)safeproc.c $(WINDHDR) $(HACK_H)
$(OGUI)consoletty.o: $(MSWSYS)consoletty.c $(WINDHDR) $(HACK_H) $(TILE_H)
$(OGUI)win10.o: $(MSWSYS)win10.c $(WINDHDR) $(HACK_H)
$(OGUI)windsys.o: $(MSWSYS)windsys.c $(WINDHDR) $(HACK_H)
$(OGUI)windsound.o: $(WINDSOUNDDIR)windsound.c $(HACK_H)
$(OGUI)windmain.o: $(MSWSYS)windmain.c $(WINDHDR) $(HACK_H)
+$(OGUI)safeproc.o: $(WSHR)safeproc.c $(WINDHDR) $(HACK_H)
#===================================================================
# win/win32 dependencies
diff --git a/sys/windows/consoletty.c b/sys/windows/consoletty.c
index bceb98132..34489430f 100644
--- a/sys/windows/consoletty.c
+++ b/sys/windows/consoletty.c
@@ -156,6 +156,7 @@ static boolean check_font_widths(void);
#endif
static void set_known_good_console_font(void);
static void restore_original_console_font(void);
+extern void safe_routines(void);
void tty_ibmgraphics_fixup(void);
#ifdef VIRTUAL_TERMINAL_SEQUENCES
extern void (*ibmgraphics_mode_callback)(void); /* symbols.c */
@@ -1188,6 +1189,8 @@ consoletty_open(int mode UNUSED)
void
consoletty_exit(void)
{
+ /* go back to using the safe routines */
+ safe_routines();
free_custom_colors();
free((genericptr_t) console.front_buffer);
free((genericptr_t) console.back_buffer);
@@ -2543,13 +2546,9 @@ void early_raw_print(const char *s)
void nethack_enter_consoletty(void)
{
- int width;
#ifdef VIRTUAL_TERMINAL_SEQUENCES
char buf[BUFSZ], *bp, *localestr;
BOOL apisuccess;
-// DWORD unused;
-// int i = 0;
-
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
#if 0
/* set up state needed by early_raw_print() */
@@ -2563,38 +2562,13 @@ void nethack_enter_consoletty(void)
GetWindowLong(console.hWnd, GWL_STYLE)
& ~WS_MAXIMIZEBOX & ~WS_SIZEBOX);
#endif
-
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
- /* srWindow identifies the visible area; dwSize identifies the buffer
- */
- width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
- fprintf(stdout, "width = %d\n", width);
- }
-
console.hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
nhassert(console.hConOut != NULL); // NOTE: this assert will not print
GetConsoleScreenBufferInfo(console.hConOut, &console.orig_csbi);
- //COORD screencheck = GetLargestConsoleWindowSize(console.hConOut);
-
- GetConsoleMode(console.hConOut, &console.orig_out_cmode);
- console.out_cmode = console.orig_out_cmode;
- console.out_cmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- SetConsoleMode(console.hConOut, console.out_cmode);
-#if 0
- /* tests */
- WriteConsoleA(console.hConOut, "\033[8;;133t",9, &unused, NULL);
- for (i = 0; i < 13; ++i) {
- WriteConsoleA(console.hConOut, "0123456789", 10, &unused, NULL);
- }
- WriteConsoleA(console.hConOut, "\033[3;133ftest", 12, &unused, NULL);
- GetConsoleScreenBufferInfo(console.hConOut, &console.orig_csbi);
/* Testing of widths != COLNO has not turned up any problems. Need
* to do a bit more testing and then we are likely to enable having
* console width match window width.
*/
-#endif
-
#if 0
console.width = console.orig_csbi.srWindow.Right -
console.orig_csbi.srWindow.Left + 1;
diff --git a/sys/windows/vs/NetHack/NetHack.vcxproj b/sys/windows/vs/NetHack/NetHack.vcxproj
index c6f2df87c..131a4cf05 100644
--- a/sys/windows/vs/NetHack/NetHack.vcxproj
+++ b/sys/windows/vs/NetHack/NetHack.vcxproj
@@ -74,7 +74,7 @@
Speed
true
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);%(AdditionalIncludeDirectories)
- WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;SND_SOUNDEFFECTS_AUTOMAP;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;%(PreprocessorDefinitions)
+ WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;SND_SOUNDEFFECTS_AUTOMAP;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;%(PreprocessorDefinitions)
stdclatest
@@ -218,6 +218,7 @@
+
diff --git a/sys/windows/vs/NetHackW/NetHackW.vcxproj b/sys/windows/vs/NetHackW/NetHackW.vcxproj
index cc3ec2563..fce2d2a1d 100644
--- a/sys/windows/vs/NetHackW/NetHackW.vcxproj
+++ b/sys/windows/vs/NetHackW/NetHackW.vcxproj
@@ -87,7 +87,7 @@
Disabled
true
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);%(AdditionalIncludeDirectories)
- TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;NOTTYGRAPHICS;SND_LIB_WINDSOUND;USER_SOUNDS;SND_SOUNDEFFECTS_AUTOMAP;HAS_STDINT_H;HAS_INTTYPES_H;PDC_WIDE;%(PreprocessorDefinitions)
+ TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;SAFEPROCS;NOTTYGRAPHICS;SND_LIB_WINDSOUND;USER_SOUNDS;SND_SOUNDEFFECTS_AUTOMAP;HAS_STDINT_H;HAS_INTTYPES_H;PDC_WIDE;%(PreprocessorDefinitions)
stdclatest
stdclatest
stdclatest
@@ -263,6 +263,7 @@
+
diff --git a/sys/windows/vs/sfctool/sfctool.vcxproj b/sys/windows/vs/sfctool/sfctool.vcxproj
index ad1971969..5dff90066 100644
--- a/sys/windows/vs/sfctool/sfctool.vcxproj
+++ b/sys/windows/vs/sfctool/sfctool.vcxproj
@@ -150,7 +150,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -166,7 +166,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -186,7 +186,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -202,7 +202,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -218,7 +218,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -238,7 +238,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_NDEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
stdclatest
true
@@ -258,4 +258,4 @@
-
+
\ No newline at end of file
diff --git a/sys/windows/vs/sftags/sftags.vcxproj b/sys/windows/vs/sftags/sftags.vcxproj
index 52c63d47a..43f024c24 100644
--- a/sys/windows/vs/sftags/sftags.vcxproj
+++ b/sys/windows/vs/sftags/sftags.vcxproj
@@ -110,7 +110,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -125,7 +125,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -144,7 +144,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -159,7 +159,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -174,7 +174,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -194,7 +194,7 @@
$(WinWin32Dir);$(IncDir);$(SysWindDir);$(SysShareDir);$(WinShareDir);$(LuaDir);$(UtilDir);%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32CON;NO_TILE_C;DLB;SAFEPROCS;SND_LIB_WINDSOUND;USER_SOUNDS;_LIB;HAS_STDINT_H;HAS_INTTYPES_H;SFCTOOL;NOPANICTRACE;NOCRASHREPORT;NO_CHRONICLE;%(PreprocessorDefinitions)
Level3
true
true
@@ -223,4 +223,4 @@
-
+
\ No newline at end of file
diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c
index c50a6d292..9e34152ac 100644
--- a/sys/windows/windmain.c
+++ b/sys/windows/windmain.c
@@ -14,6 +14,10 @@
#include
#include
+#if !defined(SAFEPROCS)
+#error You must #define SAFEPROCS to build windmain.c
+#endif
+
static void nhusage(void);
char *exename(void);
boolean fakeconsole(void);
@@ -63,6 +67,7 @@ char windows_yn_function(const char *, const char *, char);
#ifdef WIN32CON
extern int windows_console_custom_nhgetch(void);
+void safe_routines(void);
int tty_self_recover_prompt(void);
#endif
@@ -101,13 +106,6 @@ void update_file(const char *, const char *,
const char *, const char *, BOOL);
void windows_raw_print_bold(const char *);
-staticfn void set_emergency_io(void);
-staticfn void stdio_wait_synch(void);
-staticfn void stdio_raw_print(const char *str);
-staticfn void stdio_nonl_raw_print(const char *str);
-staticfn void stdio_raw_print_bold(const char *str);
-staticfn int stdio_nhgetch(void);
-
#ifdef PORT_HELP
void port_help(void);
#endif
@@ -161,9 +159,18 @@ MAIN(int argc, char *argv[])
char *dir = NULL;
#ifdef _MSC_VER
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
+#ifdef WIN32CON
+ /*
+ * Get a set of valid safe windowport function
+ * pointers during early startup initialization.
+ */
+// safe_routines();
+#endif /* WIN32CON */
+
+
/* setting iflags.colorcount has to be after early_init()
* because it zeros out all of iflags */
hwnd = GetDesktopWindow();
@@ -201,9 +208,8 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
#ifndef MSWIN_GRAPHICS
early_init(argc, argv); /* already in WinMain for MSWIN_GRAPHICS */
#endif
- set_default_prefix_locations(
- argv[0]); /* must be re-done after initoptions_init()
- * which clears out gp.fqn_prefix[] */
+ set_default_prefix_locations(argv[0]); /* must be re-done after initoptions_init()
+ * which clears out gp.fqn_prefix[] */
copy_sysconf_content();
copy_symbols_content();
/* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't
@@ -211,20 +217,13 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
fqn_prefix_locked[TROUBLEPREFIX] = TRUE;
copy_config_content();
- // if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
- // windowtype = gc.chosen_windowtype;
- // windowtype = gc.chosen_windowtype;
+ // if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
+ // windowtype = gc.chosen_windowtype;
+ // windowtype = gc.chosen_windowtype;
#if !defined(MSWIN_GRAPHICS)
- nethack_enter_consoletty();
consoletty_open(1);
-#endif
- set_emergency_io();
-
-#ifdef EARLY_CONFIGFILE_PASS
- rcfile_interface_options();
- if (gc.chosen_windowtype && *gc.chosen_windowtype)
- windowtype = gc.chosen_windowtype;
+ nethack_enter_consoletty();
#endif
if (!windowtype) {
@@ -234,10 +233,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
windowtype = "tty";
#endif
}
- choose_windows(
- windowtype); /* sets all the window port function pointers */
-
- init_nhwindows(&argc, argv);
+ choose_windows(windowtype); /* sets all the window port function pointers */
#if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
/* Save current directory and make sure it gets restored when
@@ -247,9 +243,8 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
error("NetHack: current directory path too long");
#endif
initoptions_init(); // This allows OPTIONS in syscf on Windows.
- set_default_prefix_locations(
- argv[0]); /* must be re-done after initoptions_init()
- * which clears out gp.fqn_prefix[] */
+ set_default_prefix_locations(argv[0]); /* must be re-done after initoptions_init()
+ * which clears out gp.fqn_prefix[] */
iflags.windowtype_deferred = TRUE;
program_state.early_options = 1;
@@ -291,6 +286,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
&& (strstri(argv[0], "nethackw.exe") || GUILaunched))
iflags.windowtype_locked = TRUE;
#endif
+ windowtype = default_window_sys;
#ifdef DLB
if (!dlb_init()) {
@@ -305,6 +301,18 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
}
#endif
+ if (!iflags.windowtype_locked) {
+#if defined(TTY_GRAPHICS)
+ Strcpy(default_window_sys, "tty");
+#else
+#if defined(CURSES_GRAPHICS) && !defined(MSWIN_GRAPHICS)
+ Strcpy(default_window_sys, "curses");
+#endif /* CURSES */
+#endif /* TTY */
+ // if (iflags.windowtype_deferred && gc.chosen_windowtype[0])
+ // windowtype = gc.chosen_windowtype;
+ }
+ // choose_windows(windowtype);
#if defined(SND_LIB_FMOD)
assign_soundlib(soundlib_fmod);
#elif defined(SND_LIB_WINDSOUND)
@@ -314,14 +322,19 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
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;
+#ifdef WIN32CON
+ if (WINDOWPORT(tty))
+ consoletty_open(1);
+#endif
#ifdef WINCHAIN
commit_windowchain();
#endif
-// init_nhwindows(&argc, argv);
+ init_nhwindows(&argc, argv);
#ifdef WIN32CON
if (WINDOWPORT(tty))
@@ -824,6 +837,20 @@ copy_hack_content(void)
gf.fqn_prefix[DATAPREFIX], OPTIONFILE, FALSE);
}
+#ifdef WIN32CON
+void
+safe_routines(void)
+{
+ /*
+ * Get a set of valid safe windowport function
+ * pointers during early startup initialization.
+ */
+ if (!WINDOWPORT(safestartup))
+ windowprocs = *get_safe_procs(1);
+ if (!GUILaunched)
+ windowprocs.win_nhgetch = windows_console_custom_nhgetch;
+}
+#endif
#ifdef PORT_HELP
void
@@ -1178,7 +1205,9 @@ tty_self_recover_prompt(void)
c = 'n';
ct = 0;
saved_procs = windowprocs;
-
+ if (!WINDOWPORT(safestartup))
+ windowprocs = *get_safe_procs(2); /* arg 2 uses no-newline variant */
+ windowprocs.win_nhgetch = windows_console_custom_nhgetch;
raw_print("\n");
raw_print("\n");
raw_print("\n");
@@ -1311,60 +1340,4 @@ chdirx(const char *dir, boolean wr)
}
#endif /* CHDIR */
-void
-set_emergency_io(void)
-{
- windowprocs.win_raw_print = stdio_raw_print;
- windowprocs.win_raw_print_bold = stdio_raw_print_bold;
- windowprocs.win_nhgetch = stdio_nhgetch;
- windowprocs.win_wait_synch = stdio_wait_synch;
-}
-
-
-/* Add to your code: windowprocs.win_raw_print = stdio_wait_synch; */
-void
-stdio_wait_synch(void)
-{
- char valid[] = { ' ', '\n', '\r', '\033', '\0' };
-
- fprintf(stdout, "--More--");
- (void) fflush(stdout);
- while (!strchr(valid, nhgetch()))
- ;
-}
-
-/* Add to your code: windowprocs.win_raw_print = stdio_raw_print; */
-void
-stdio_raw_print(const char *str)
-{
- if (str)
- fprintf(stdout, "%s\n", str);
- return;
-}
-
-/* no newline variation, add to your code:
- windowprocs.win_raw_print = stdio_nonl_raw_print; */
-void
-stdio_nonl_raw_print(const char *str)
-{
- if (str)
- fprintf(stdout, "%s", str);
- return;
-}
-
-/* Add to your code: windowprocs.win_raw_print_bold = stdio_raw_print_bold; */
-void
-stdio_raw_print_bold(const char *str)
-{
- stdio_raw_print(str);
- return;
-}
-
-/* Add to your code: windowprocs.win_nhgetch = stdio_nhgetch; */
-int
-stdio_nhgetch(void)
-{
- return getchar();
-}
-
- /*windmain.c*/
+/*windmain.c*/
diff --git a/sys/windows/windsys.c b/sys/windows/windsys.c
index aca0cfe9e..88f1a69bf 100644
--- a/sys/windows/windsys.c
+++ b/sys/windows/windsys.c
@@ -73,6 +73,7 @@ static HWND GetConsoleHwnd(void);
extern void backsp(void);
#endif
int windows_console_custom_nhgetch(void);
+extern void safe_routines(void);
int windows_early_options(const char *window_opt);
unsigned long sys_random_seed(void);
#if 0
@@ -292,6 +293,10 @@ win32_abort(void)
exit_nhwindows((char *) 0);
iflags.window_inited = FALSE;
}
+#ifdef WIN32CON
+ if (!WINDOWPORT(mswin) && !WINDOWPORT(safestartup))
+ safe_routines();
+#endif
if (wizard) {
raw_print("Execute debug breakpoint wizard?");
if ((c = nhgetch()) == 'y' || c == 'Y')
@@ -517,6 +522,15 @@ nethack_exit(int code)
* GUILaunched is defined and set in consoletty.c.
*/
+
+#ifdef WIN32CON
+ if (!GUILaunched) {
+ windowprocs = *get_safe_procs(1);
+ /* use our custom version which works
+ a little cleaner than the stdio one */
+ windowprocs.win_nhgetch = windows_console_custom_nhgetch;
+ } else
+#endif
if (getreturn_enabled) {
raw_print("\n");
if (iflags.window_inited)
@@ -566,6 +580,10 @@ getreturn(const char *str)
initializing the window port */
void nethack_enter_windows(void)
{
+#ifdef WIN32CON
+ if (WINDOWPORT(tty))
+ nethack_enter_consoletty();
+#endif
}
/* CP437 to Unicode mapping according to the Unicode Consortium */
diff --git a/win/share/safeproc.c b/win/share/safeproc.c
new file mode 100644
index 000000000..19e9aa9b6
--- /dev/null
+++ b/win/share/safeproc.c
@@ -0,0 +1,596 @@
+/* NetHack 3.7 safeproc.c */
+/* Copyright (c) Michael Allison, 2018 */
+/* NetHack may be freely redistributed. See license for details. */
+
+/* must #define SAFEPROCS in xxxconf.h or via CFLAGS or this won't compile */
+#include "hack.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(n)
+ * call.
+ *
+ * Usage:
+ *
+ * windowprocs = *get_safe_procs(0);
+ * initializes a set of winprocs function pointers that ensure
+ * none of the function pointers are left null, but that's all
+ * it does.
+ *
+ * windowprocs = *get_safe_procs(1);
+ * initializes a set of winprocs functions pointers that ensure
+ * none of the function pointers are left null, but also
+ * provides some basic output and input functionality using
+ * nothing other than C stdio routines (no platform-specific
+ * or OS-specific code).
+ *
+ * ***********************************************************
+ */
+
+void safe_dismiss_nhwindow(winid);
+void safe_putstr(winid, int, const char *);
+void win_safe_init(int);
+void safe_number_pad(int);
+
+struct window_procs safe_procs = {
+ WPID(safestartup),
+ (0
+#ifdef TTY_PERM_INVENT
+ | WC_PERM_INVENT
+#endif
+#ifdef MSDOS
+ | WC_TILED_MAP | WC_ASCII_MAP
+#endif
+#if defined(WIN32CON)
+ | WC_MOUSE_SUPPORT
+#endif
+ | WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN),
+ (0
+#if defined(SELECTSAVED)
+ | WC2_SELECTSAVED
+#endif
+#if defined(STATUS_HILITES)
+ | WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
+ | WC2_RESET_STATUS
+#endif
+ | WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES
+ | WC2_U_UTF8STR | WC2_PETATTR
+#if !defined(NO_TERMS) || defined(WIN32CON)
+ | WC2_EXTRACOLORS
+#endif
+ ),
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
+ 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, safe_putmixed,
+ safe_display_file, safe_start_menu, safe_add_menu, safe_end_menu,
+ safe_select_menu, safe_message_menu,
+ 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_outrip,
+ safe_preference_update,
+ safe_getmsghistory, safe_putmsghistory,
+ safe_status_init,
+ safe_status_finish, safe_status_enablefield,
+ safe_status_update,
+ safe_can_suspend,
+ safe_update_inventory,
+ safe_ctrl_nhwindow,
+};
+
+struct window_procs *
+get_safe_procs(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;
+ if (optn == 2)
+ safe_procs.win_raw_print = stdio_nonl_raw_print;
+ }
+ return &safe_procs;
+}
+
+/*ARGSUSED*/
+void
+safe_init_nhwindows(int *argcp UNUSED, char **argv UNUSED)
+{
+ return;
+}
+
+void
+safe_player_selection(void)
+{
+ return;
+}
+
+void
+safe_askname(void)
+{
+ return;
+}
+
+void
+safe_get_nh_event(void)
+{
+ return;
+}
+
+void
+safe_suspend_nhwindows(const char *str UNUSED)
+{
+ return;
+}
+
+void
+safe_resume_nhwindows(void)
+{
+ return;
+}
+
+void
+safe_exit_nhwindows(const char *str UNUSED)
+{
+ return;
+}
+
+winid
+safe_create_nhwindow(int type UNUSED)
+{
+ return WIN_ERR;
+}
+
+void
+safe_clear_nhwindow(winid window UNUSED)
+{
+ return;
+}
+
+/*ARGSUSED*/
+void
+safe_display_nhwindow(winid window UNUSED, boolean blocking UNUSED)
+{
+ return;
+}
+
+void
+safe_dismiss_nhwindow(winid window UNUSED)
+{
+ return;
+}
+
+void
+safe_destroy_nhwindow(winid window UNUSED)
+{
+ return;
+}
+
+void
+safe_curs(winid window UNUSED, int x UNUSED, int y UNUSED)
+{
+ return;
+}
+
+void
+safe_putstr(winid window UNUSED, int attr UNUSED, const char *str UNUSED)
+{
+ return;
+}
+
+void
+safe_putmixed(winid window UNUSED, int attr UNUSED, const char *str UNUSED)
+{
+ return;
+}
+
+void
+safe_display_file(const char * fname UNUSED, boolean complain UNUSED)
+{
+ return;
+}
+
+void
+safe_start_menu(winid window UNUSED, unsigned long mbehavior UNUSED)
+{
+ return;
+}
+
+/*ARGSUSED*/
+/*
+ * Add a menu item to the beginning of the menu list. This list is reversed
+ * later.
+ */
+void
+safe_add_menu(
+ winid window UNUSED, /* window to use, must be of type NHW_MENU */
+ const glyph_info *glyphinfo UNUSED, /* glyph plus glyph info */
+ const anything *identifier UNUSED, /* what to return if selected */
+ char ch UNUSED, /* keyboard accelerator (0 = pick our own) */
+ char gch UNUSED, /* group accelerator (0 = no group) */
+ int attr UNUSED, /* attribute for string (like safe_putstr()) */
+ int clr UNUSED, /* colour for string */
+ const char *str UNUSED, /* menu string */
+ unsigned int itemflags UNUSED) /* itemflags such as marked as selected */
+{
+ return;
+}
+
+/*
+ * End a menu in this window, window must a type NHW_MENU.
+ */
+void
+safe_end_menu(
+ winid window UNUSED, /* menu to use */
+ const char *prompt UNUSED) /* prompt to for menu */
+{
+ return;
+}
+
+int
+safe_select_menu(
+ winid window UNUSED,
+ int how UNUSED,
+ menu_item **menu_list UNUSED)
+{
+ return 0;
+}
+
+/* special hack for treating top line --More-- as a one item menu */
+char
+safe_message_menu(
+ char let UNUSED,
+ int how UNUSED,
+ const char *mesg UNUSED)
+{
+ return '\033';
+}
+
+void
+safe_mark_synch(void)
+{
+}
+
+void
+safe_wait_synch(void)
+{
+}
+
+#ifdef CLIPPING
+void
+safe_cliparound(int x UNUSED, int y UNUSED)
+{
+}
+#endif /* CLIPPING */
+
+/*
+ * safe_print_glyph
+ *
+ * Print the glyph to the output device. Don't flush the output device.
+ */
+void
+safe_print_glyph(
+ winid window UNUSED,
+ coordxy x UNUSED,
+ coordxy y UNUSED,
+ const glyph_info *glyphinfo UNUSED,
+ const glyph_info *bkglyphinfo UNUSED)
+{
+ return;
+}
+
+void
+safe_raw_print(const char *str UNUSED)
+{
+ return;
+}
+
+void
+safe_raw_print_bold(const char *str UNUSED)
+{
+ return;
+}
+
+int
+safe_nhgetch(void)
+{
+ return '\033';
+}
+
+/*
+ * return a key, or 0, in which case a mouse button was pressed
+ * mouse events should be returned as character positions in the map window.
+ * Since normal tty's don't have mice, just return a key.
+ */
+/*ARGSUSED*/
+int
+safe_nh_poskey(coordxy *x UNUSED, coordxy *y UNUSED, int *mod UNUSED)
+{
+ return '\033';
+}
+
+void
+win_safe_init(int dir UNUSED)
+{
+ return;
+}
+
+#ifdef POSITIONBAR
+void
+safe_update_positionbar(char *posbar UNUSED)
+{
+ return;
+}
+#endif /* POSITIONBAR */
+
+/*
+ * safe_status_init()
+ * -- initialize the port-specific data structures.
+ */
+void
+safe_status_init(void)
+{
+ return;
+}
+
+boolean
+safe_can_suspend(void)
+{
+ return FALSE;
+}
+
+void
+safe_nhbell(void)
+{
+ return;
+}
+
+int
+safe_doprev_message(void)
+{
+ return 0;
+}
+
+char
+safe_yn_function(const char *query UNUSED,
+ const char *resp UNUSED, char def UNUSED)
+{
+ return '\033';
+}
+
+/*ARGSUSED*/
+void
+safe_getlin(const char* prompt UNUSED, char *outbuf)
+{
+ Strcpy(outbuf, "\033");
+}
+
+int
+safe_get_ext_cmd(void)
+{
+ return '\033';
+}
+
+void
+safe_number_pad(int mode UNUSED)
+{
+ return;
+}
+
+void
+safe_delay_output(void)
+{
+ return;
+}
+
+void
+safe_outrip(winid tmpwin UNUSED, int how UNUSED, time_t when UNUSED)
+{
+ return;
+}
+
+/*ARGSUSED*/
+void
+safe_preference_update(const char *pref UNUSED)
+{
+ return;
+}
+
+char *
+safe_getmsghistory(boolean init UNUSED)
+{
+ return (char *) 0;
+}
+
+void
+safe_putmsghistory(
+ const char *msg UNUSED,
+ boolean is_restoring UNUSED)
+{
+}
+
+void
+safe_status_finish(void)
+{
+}
+
+void
+safe_status_enablefield(
+ int fieldidx UNUSED,
+ const char *nm UNUSED,
+ const char *fmt UNUSED,
+ boolean enable UNUSED)
+{
+}
+
+/* call once for each field, then call with BL_FLUSH to output the result */
+void
+safe_status_update(
+ int idx UNUSED,
+ genericptr_t ptr UNUSED,
+ int chg UNUSED,
+ int percent UNUSED,
+ int color UNUSED,
+ unsigned long *colormasks UNUSED)
+{
+}
+
+void
+safe_update_inventory(int arg UNUSED)
+{
+ return;
+}
+
+#ifdef WIN32CON
+extern win_request_info *tty_ctrl_nhwindow(winid window UNUSED,
+ int request UNUSED,
+ win_request_info *wri UNUSED);
+#endif
+
+win_request_info *
+safe_ctrl_nhwindow(
+ winid window UNUSED,
+ int request UNUSED,
+ win_request_info *wri UNUSED)
+{
+#ifdef WIN32CON
+ return (*tty_ctrl_nhwindow)(window, request, wri);
+#else
+ return (win_request_info *) 0;
+#endif
+}
+
+/**************************************************************
+ * 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(void)
+{
+ char valid[] = {' ', '\n', '\r', '\033', '\0'};
+
+ fprintf(stdout, "--More--");
+ (void) fflush(stdout);
+ while (!strchr(valid, nhgetch()))
+ ;
+}
+
+/* Add to your code: windowprocs.win_raw_print = stdio_raw_print; */
+void
+stdio_raw_print(const char *str)
+{
+ if (str)
+ fprintf(stdout, "%s\n", str);
+ return;
+}
+
+/* no newline variation, add to your code:
+ windowprocs.win_raw_print = stdio_nonl_raw_print; */
+void
+stdio_nonl_raw_print(const char *str)
+{
+ if (str)
+ fprintf(stdout, "%s", str);
+ return;
+}
+
+/* Add to your code: windowprocs.win_raw_print_bold = stdio_raw_print_bold; */
+void
+stdio_raw_print_bold(const char *str)
+{
+ stdio_raw_print(str);
+ return;
+}
+
+/* Add to your code: windowprocs.win_nhgetch = stdio_nhgetch; */
+int
+stdio_nhgetch(void)
+{
+ return getchar();
+}
+
+#ifdef CHANGE_COLOR
+void
+safe_change_color(int color UNUSED, long rgb UNUSED, int reverse UNUSED)
+{
+}
+
+char *
+safe_get_color_string(void)
+{
+ return ("");
+}
+
+
+#endif
+
+/* safeprocs.c */
diff --git a/win/tty/wintty.c b/win/tty/wintty.c
index 4cbe65a2a..61338542b 100644
--- a/win/tty/wintty.c
+++ b/win/tty/wintty.c
@@ -3559,9 +3559,8 @@ assesstty(
short *offx, short *offy, long *rows, long *cols,
long *maxcol, long *minrow, long *maxrow)
{
- boolean inuse_only = (invmode & (int) InvInUse) != 0,
- show_gold = (invmode & (int) InvShowGold) != 0
- && !inuse_only;
+ boolean inuse_only = (invmode & InvInUse) != 0,
+ show_gold = (invmode & InvShowGold) != 0 && !inuse_only;
int perminv_minrow = tty_perminv_minrow + (show_gold ? 1 : 0);
if (!ttyDisplay) {
diff --git a/win/win32/NetHackW.c b/win/win32/NetHackW.c
index 56d8bb7c7..92b851c7a 100644
--- a/win/win32/NetHackW.c
+++ b/win/win32/NetHackW.c
@@ -15,6 +15,10 @@
#include "mhmain.h"
#include "mhmap.h"
+#if !defined(SAFEPROCS)
+#error You must #define SAFEPROCS to build NetHackW.c
+#endif
+
/* Borland and MinGW redefine "boolean" in shlwapi.h,
so just use the little bit we need */
typedef struct _DLLVERSIONINFO {
@@ -95,6 +99,32 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
+ /*
+ * 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();
early_init(0, NULL); /* Change as needed to support CRASHREPORT */
diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c
index 55ba2f696..abef776da 100644
--- a/win/win32/mswproc.c
+++ b/win/win32/mswproc.c
@@ -734,6 +734,9 @@ mswin_exit_nhwindows(const char *str)
/* Write Window settings to the registry */
mswin_write_reg();
+ /* set things back to failsafes */
+ windowprocs = *get_safe_procs(0);
+
/* and make sure there is still a way to communicate something */
windowprocs.win_raw_print = mswin_raw_print;
windowprocs.win_raw_print_bold = mswin_raw_print_bold;