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;