From 518e067e82afeea7a00aa160a0bff949c011e026 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 7 Feb 2016 00:36:46 -0800 Subject: [PATCH] X11 default resources If the user hasn't explicitly loaded application defaults (which I haven't been doing), the X11 interface behaves differently if invoked via the shell script than if the executable is run directly, because the script sets up a path so that X can find $HACKDIR/NetHack.ad. This hides the difference by reading in that file during initialization and feeding its contents to XtAppInitialize as fallback resources. --- win/X11/winX.c | 137 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 34 deletions(-) diff --git a/win/X11/winX.c b/win/X11/winX.c index 93d8ca2cc..b0714ab5b 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 winX.c $NHDT-Date: 1454810422 2016/02/07 02:00:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */ +/* NetHack 3.6 winX.c $NHDT-Date: 1454834200 2016/02/07 08:36:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -138,22 +138,31 @@ struct window_procs X11_procs = { /* * Local functions. */ -static void FDECL(dismiss_file, (Widget, XEvent *, String *, Cardinal *)); -static void FDECL(delete_file, (Widget, XEvent *, String *, Cardinal *)); -static void FDECL(yn_key, (Widget, XEvent *, String *, Cardinal *)); -static void FDECL(yn_delete, (Widget, XEvent *, String *, Cardinal *)); +static winid NDECL(find_free_window); +static void FDECL(nhFreePixel, (XtAppContext, XrmValuePtr, XtPointer, + XrmValuePtr, Cardinal *)); +static void NDECL(load_default_resources); +static void NDECL(release_default_resources); +#ifdef X11_HANGUP_SIGNAL +static void FDECL(X11_sig, (int)); +static void FDECL(X11_sig_cb, (XtPointer, XtSignalId *)); +#endif +static void FDECL(d_timeout, (XtPointer, XtIntervalId *)); +static void FDECL(X11_hangup, (Widget, XEvent *, String *, Cardinal *)); static void FDECL(askname_delete, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(askname_done, (Widget, XtPointer, XtPointer)); +static void FDECL(done_button, (Widget, XtPointer, XtPointer)); static void FDECL(getline_delete, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(abort_button, (Widget, XtPointer, XtPointer)); static void NDECL(release_getline_widgets); -static void FDECL(X11_hangup, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(delete_file, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(dismiss_file, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(yn_delete, (Widget, XEvent *, String *, Cardinal *)); +static void FDECL(yn_key, (Widget, XEvent *, String *, Cardinal *)); static void NDECL(release_yn_widgets); static int FDECL(input_event, (int)); static void FDECL(win_visible, (Widget, XtPointer, XEvent *, Boolean *)); static void NDECL(init_standard_windows); -#ifdef X11_HANGUP_SIGNAL -static void FDECL(X11_sig, (int)); -static void FDECL(X11_sig_cb, (XtPointer, XtSignalId *)); -#endif /* * Local variables. @@ -474,8 +483,77 @@ Widget w; #endif } -/* Global Functions ======================================================== - */ +static String *default_resource_data = 0; /* NULL-terminated array */ + +/* read the template NetHack.ad into default_resource_data[] to supply + fallback resources to XtAppInitialize() */ +static void +load_default_resources() +{ + FILE *fp; + String inbuf; + unsigned insiz, linelen, longlen, numlines; + boolean comment = FALSE; /* lint suppression */ + + /* + * Running nethack via the shell script adds $HACKDIR to the path used + * by X to find resources, but running it directly doesn't. So, if we + * can find the template file for NetHack.ad in the current directory, + * load its contents into memory so that the application startup call + * in X11_init_nhwindows() can use them as fallback resources. + */ + fp = fopen("./NetHack.ad", "r"); + if (!fp) + return; + + /* measure the file without retaining its contents */ + insiz = BUFSIZ; /* stdio BUFSIZ, not nethack BUFSZ */ + inbuf = (String) alloc(insiz); + linelen = longlen = 0; + numlines = 0; + while (fgets(inbuf, insiz, fp)) { + if (!linelen) /* inbuf has start of record; treat empty as comment */ + comment = (*inbuf == '!' || *inbuf == '\n'); + linelen += strlen(inbuf); + if (!index(inbuf, '\n')) + continue; + if (linelen > longlen) + longlen = linelen; + linelen = 0; + if (!comment) + ++numlines; + } + free((genericptr_t) inbuf); + insiz = longlen + 1; + inbuf = (String) alloc(insiz); + ++numlines; /* room for terminator */ + default_resource_data = (String *) alloc(numlines * sizeof (String)); + + /* now read the file into the array */ + (void) rewind(fp); + numlines = 0; + while (fgets(inbuf, insiz, fp)) { + if (*inbuf != '!' && *inbuf != '\n') + default_resource_data[numlines++] = dupstr(inbuf); + } + default_resource_data[numlines] = (String) 0; + (void) fclose(fp); + free((genericptr_t) inbuf); +} + +static void +release_default_resources() +{ + if (default_resource_data) { + unsigned idx; + + for (idx = 0; default_resource_data[idx]; idx++) + free((genericptr_t) default_resource_data[idx]); + free((genericptr_t) default_resource_data), default_resource_data = 0; + } +} + +/* Global Functions ======================================================= */ void X11_raw_print(str) const char *str; @@ -930,8 +1008,7 @@ time_t when; } #endif -/* init and exit nhwindows ------------------------------------------------- - */ +/* init and exit nhwindows ------------------------------------------------ */ XtAppContext app_context; /* context of application */ Widget toplevel = (Widget) 0; /* toplevel widget */ @@ -1023,6 +1100,8 @@ char **argv; /* add another option that can be set */ set_wc_option_mod_status(WC_TILED_MAP, SET_IN_GAME); + load_default_resources(); /* create default_resource_data[] */ + /* * setuid hack: make sure that if nethack is setuid, to use real uid * when opening X11 connections, in case the user is using xauth, since @@ -1038,15 +1117,10 @@ char **argv; num_args = 0; XtSetArg(args[num_args], XtNallowShellResize, True); num_args++; - /* - * TODO? Find and load NetHack.ad (installation puts a template copy - * in the playground directory) if the server doesn't already have it. - */ - toplevel = XtAppInitialize(&app_context, "NetHack", /* application */ (XrmOptionDescList) 0, 0, /* options list */ argcp, (String *) argv, /* command line */ - (String *) 0, /* fallback resources */ + default_resource_data, /* fallback resources */ (ArgList) args, num_args); XtOverrideTranslations(toplevel, XtParseTranslationTable("WM_PROTOCOLS: X11_hangup()")); @@ -1098,6 +1172,8 @@ char **argv; x_inited = TRUE; /* X is now initialized */ + release_default_resources(); + /* Display the startup banner in the message window. */ for (i = 1; i <= 4 + 2; ++i) /* (values beyond 4 yield blank lines) */ X11_putstr(WIN_MESSAGE, 0, copyright_banner_line(i)); @@ -1169,8 +1245,7 @@ XtSignalId *id; } #endif -/* delay_output ------------------------------------------------------------ - */ +/* delay_output ----------------------------------------------------------- */ /* * Timeout callback for delay_output(). Send a fake message to the map @@ -1216,8 +1291,7 @@ X11_delay_output() (void) x_event(EXIT_ON_SENT_EVENT); } -/* X11_hangup -------------------------------------------------------------- - */ +/* X11_hangup ------------------------------------------------------------- */ /* ARGSUSED */ static void X11_hangup(w, event, params, num_params) @@ -1235,8 +1309,7 @@ Cardinal *num_params; exit_x_event = TRUE; } -/* askname ----------------------------------------------------------------- - */ +/* askname ---------------------------------------------------------------- */ /* ARGSUSED */ static void askname_delete(w, event, params, num_params) @@ -1322,8 +1395,7 @@ X11_askname() XtDestroyWidget(popup); } -/* getline ----------------------------------------------------------------- - */ +/* getline ---------------------------------------------------------------- */ /* This uses Tim Theisen's dialog widget set (from GhostView). */ static Widget getline_popup, getline_dialog; @@ -1448,8 +1520,7 @@ char *input; (void) x_event(EXIT_ON_EXIT); } -/* Display file ------------------------------------------------------------ - */ +/* Display file ----------------------------------------------------------- */ static const char display_translations[] = "#override\n\ q: dismiss_file()\n\ Escape: dismiss_file()\n\ @@ -1606,8 +1677,7 @@ boolean complain; free(textlines); } -/* yn_function ------------------------------------------------------------- - */ +/* yn_function ------------------------------------------------------------ */ /* (not threaded) */ static const char *yn_quitchars = " \n\r"; @@ -1908,8 +1978,7 @@ const char *pref; } } -/* End global functions ==================================================== - */ +/* End global functions =================================================== */ /* * Before we wait for input via nhgetch() and nh_poskey(), we need to -- 2.40.0