Source:NetHack 3.4.0/options.c

From NetHackWiki
(Redirected from NetHack 3.4.0/options.c)
Jump to navigation Jump to search

Below is the full text to options.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/options.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)options.c	3.4	2002/02/07	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #ifdef OPTION_LISTS_ONLY	/* (AMIGA) external program for opt lists */
6.    #include "config.h"
7.    #include "objclass.h"
8.    #include "flag.h"
9.    NEARDATA struct flag flags;	/* provide linkage */
10.   NEARDATA struct instance_flags iflags;	/* provide linkage */
11.   #define static
12.   #else
13.   #include "hack.h"
14.   #include "tcap.h"
15.   #include <ctype.h>
16.   #endif
17.   
18.   #define WINTYPELEN 16
19.   
20.   /*
21.    *  NOTE:  If you add (or delete) an option, please update the short
22.    *  options help (option_help()), the long options help (dat/opthelp),
23.    *  and the current options setting display function (doset()),
24.    *  and also the Guidebooks.
25.    *
26.    *  The order matters.  If an option is a an initial substring of another
27.    *  option (e.g. time and timed_delay) the shorter one must come first.
28.    */
29.   
30.   static struct Bool_Opt
31.   {
32.   	const char *name;
33.   	boolean	*addr, initvalue;
34.   	int optflags;
35.   } boolopt[] = {
36.   #ifdef AMIGA
37.   	{"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME},
38.   #else
39.   	{"altmeta", (boolean *)0, TRUE, DISP_IN_GAME},
40.   #endif
41.   	{"ascii_map",     &iflags.wc_ascii_map, TRUE, SET_IN_GAME},	/*WC*/
42.   #ifdef MFLOPPY
43.   	{"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME},
44.   #else
45.   	{"asksavedisk", (boolean *)0, FALSE, SET_IN_FILE},
46.   #endif
47.   	{"autodig", &flags.autodig, FALSE, SET_IN_GAME},
48.   	{"autopickup", &flags.pickup, TRUE, SET_IN_GAME},
49.   	{"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME},
50.   #if defined(MICRO) && !defined(AMIGA)
51.   	{"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE},
52.   #else
53.   	{"BIOS", (boolean *)0, FALSE, SET_IN_FILE},
54.   #endif
55.   #ifdef INSURANCE
56.   	{"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME},
57.   #else
58.   	{"checkpoint", (boolean *)0, FALSE, SET_IN_FILE},
59.   #endif
60.   #ifdef MFLOPPY
61.   	{"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME},
62.   #else
63.   	{"checkspace", (boolean *)0, FALSE, SET_IN_FILE},
64.   #endif
65.   # ifdef MICRO
66.   	{"color",         &iflags.wc_color,TRUE, SET_IN_GAME},		/*WC*/
67.   # else	/* systems that support multiple terminals, many monochrome */
68.   	{"color",         &iflags.wc_color, FALSE, SET_IN_GAME},	/*WC*/
69.   # endif
70.   	{"confirm",&flags.confirm, TRUE, SET_IN_GAME},
71.   #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
72.   	{"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
73.   #else
74.   	{"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE},
75.   #endif
76.   	{"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME},	/*WC*/
77.   #ifdef TTY_GRAPHICS
78.   	{"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME},
79.   #else
80.   	{"extmenu", (boolean *)0, FALSE, SET_IN_FILE},
81.   #endif
82.   #ifdef OPT_DISPMAP
83.   	{"fast_map", &flags.fast_map, TRUE, SET_IN_GAME},
84.   #else
85.   	{"fast_map", (boolean *)0, TRUE, SET_IN_FILE},
86.   #endif
87.   	{"female", &flags.female, FALSE, DISP_IN_GAME},
88.   	{"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME},
89.   #ifdef AMIFLUSH
90.   	{"flush", &flags.amiflush, FALSE, SET_IN_GAME},
91.   #else
92.   	{"flush", (boolean *)0, FALSE, SET_IN_FILE},
93.   #endif
94.   	{"help", &flags.help, TRUE, SET_IN_GAME},
95.   	{"hilite_pet",    &iflags.wc_hilite_pet, FALSE, SET_IN_GAME},	/*WC*/
96.   #ifdef ASCIIGRAPH
97.   	{"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME},
98.   #else
99.   	{"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE},
100.  #endif
101.  #ifndef MAC
102.  	{"ignintr", &flags.ignintr, FALSE, SET_IN_GAME},
103.  #else
104.  	{"ignintr", (boolean *)0, FALSE, SET_IN_FILE},
105.  #endif
106.  	{"large_font", &iflags.wc_large_font, FALSE, SET_IN_FILE},	/*WC*/
107.  	{"legacy", &flags.legacy, TRUE, DISP_IN_GAME},
108.  	{"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME},
109.  #ifdef MAC_GRAPHICS_ENV
110.  	{"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME},
111.  #else
112.  	{"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE},
113.  #endif
114.  #ifdef MAIL
115.  	{"mail", &flags.biff, TRUE, SET_IN_GAME},
116.  #else
117.  	{"mail", (boolean *)0, TRUE, SET_IN_FILE},
118.  #endif
119.  #ifdef WIZARD
120.  	/* for menu debugging only*/
121.  	{"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME},
122.  #else
123.  	{"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE},
124.  #endif
125.  #ifdef TTY_GRAPHICS
126.  	{"msg_window", &iflags.prevmsg_window, FALSE, SET_IN_GAME},
127.  #else
128.  	{"msg_window", (boolean *)0, FALSE, SET_IN_FILE},
129.  #endif
130.  #ifdef NEWS
131.  	{"news", &iflags.news, TRUE, DISP_IN_GAME},
132.  #else
133.  	{"news", (boolean *)0, FALSE, SET_IN_FILE},
134.  #endif
135.  	{"null", &flags.null, TRUE, SET_IN_GAME},
136.  	{"number_pad", &iflags.num_pad, FALSE, SET_IN_GAME},
137.  #ifdef MAC
138.  	{"page_wait", &flags.page_wait, TRUE, SET_IN_GAME},
139.  #else
140.  	{"page_wait", (boolean *)0, FALSE, SET_IN_FILE},
141.  #endif
142.  	{"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME},
143.  	{"popup_dialog",  &iflags.wc_popup_dialog, FALSE, SET_IN_GAME},	/*WC*/
144.  	{"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME},
145.  	{"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME},	/*WC*/
146.  	{"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME},
147.  #if defined(MICRO) && !defined(AMIGA) && !defined(MSWIN_GRAPHICS)
148.  	{"rawio", &iflags.rawio, FALSE, DISP_IN_GAME},
149.  #else
150.  	{"rawio", (boolean *)0, FALSE, SET_IN_FILE},
151.  #endif
152.  	{"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME},
153.  	{"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
154.  #ifdef WIZARD
155.  	{"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
156.  #else
157.  	{"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
158.  #endif
159.  #ifdef EXP_ON_BOTL
160.  	{"showexp", &flags.showexp, FALSE, SET_IN_GAME},
161.  #else
162.  	{"showexp", (boolean *)0, FALSE, SET_IN_FILE},
163.  #endif
164.  #ifdef SCORE_ON_BOTL
165.  	{"showscore", &flags.showscore, FALSE, SET_IN_GAME},
166.  #else
167.  	{"showscore", (boolean *)0, FALSE, SET_IN_FILE},
168.  #endif
169.  	{"silent", &flags.silent, TRUE, SET_IN_GAME},
170.  	{"sortpack", &flags.sortpack, TRUE, SET_IN_GAME},
171.  	{"sound", &flags.soundok, TRUE, SET_IN_GAME},
172.  	{"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
173.  	{"standout", &flags.standout, FALSE, SET_IN_GAME},
174.  	{"splash_screen",     &iflags.wc_splash_screen, TRUE, DISP_IN_GAME},	/*WC*/
175.  	{"tiled_map",     &iflags.wc_tiled_map, FALSE, DISP_IN_GAME},	/*WC*/
176.  	{"time", &flags.time, FALSE, SET_IN_GAME},
177.  #ifdef TIMED_DELAY
178.  	{"timed_delay", &flags.nap, TRUE, SET_IN_GAME},
179.  #else
180.  	{"timed_delay", (boolean *)0, FALSE, SET_IN_GAME},
181.  #endif
182.  	{"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
183.  	{"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
184.  	{"use_inverse",   &iflags.wc_inverse, FALSE, SET_IN_GAME},		/*WC*/
185.  	{"verbose", &flags.verbose, TRUE, SET_IN_GAME},
186.  	{(char *)0, (boolean *)0, FALSE, 0}
187.  };
188.  
189.  /* compound options, for option_help() and external programs like Amiga
190.   * frontend */
191.  static struct Comp_Opt
192.  {
193.  	const char *name, *descr;
194.  	int size;	/* for frontends and such allocating space --
195.  			 * usually allowed size of data in game, but
196.  			 * occasionally maximum reasonable size for
197.  			 * typing when game maintains information in
198.  			 * a different format */
199.  	int optflags;
200.  } compopt[] = {
201.  	{ "align",    "your starting alignment (lawful, neutral, or chaotic)",
202.  						8, DISP_IN_GAME },
203.  	{ "align_message", "message window alignment", 20, DISP_IN_GAME }, 	/*WC*/
204.  	{ "align_status", "status window alignment", 20, DISP_IN_GAME }, 	/*WC*/
205.  #ifdef MAC
206.  	{ "background", "the color of the background (black or white)",
207.  						6, SET_IN_FILE },
208.  #endif
209.  	{ "boulder",  "the symbol to use for displaying boulders",
210.  						1, SET_IN_GAME },
211.  	{ "catname",  "the name of your (first) cat (e.g., catname:Tabby)",
212.  						PL_PSIZ, DISP_IN_GAME },
213.  	{ "disclose", "the kinds of information to disclose at end of game",
214.  						sizeof(flags.end_disclose) * 2,
215.  						SET_IN_GAME },
216.  	{ "dogname",  "the name of your (first) dog (e.g., dogname:Fang)",
217.  						PL_PSIZ, DISP_IN_GAME },
218.  	{ "dungeon",  "the symbols to use in drawing the dungeon map",
219.  						MAXDCHARS+1, SET_IN_FILE },
220.  	{ "effects",  "the symbols to use in drawing special effects",
221.  						MAXECHARS+1, SET_IN_FILE },
222.  	{ "font_map", "the font to use in the map window", 40, DISP_IN_GAME },	/*WC*/
223.  	{ "font_menu", "the font to use in menus", 40, DISP_IN_GAME },		/*WC*/
224.  	{ "font_message", "the font to use in the message window",
225.  						40, DISP_IN_GAME },		/*WC*/
226.  	{ "font_size_map", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
227.  	{ "font_size_menu", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
228.  	{ "font_size_message", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
229.  	{ "font_size_status", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
230.  	{ "font_size_text", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
231.  	{ "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/
232.  	{ "font_text", "the font to use in text windows", 40, DISP_IN_GAME },	/*WC*/
233.  	{ "fruit",    "the name of a fruit you enjoy eating",
234.  						PL_FSIZ, SET_IN_GAME },
235.  	{ "gender",   "your starting gender (male or female)",
236.  						8, DISP_IN_GAME },
237.  	{ "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
238.  						PL_PSIZ, DISP_IN_GAME },
239.  	{ "map_mode", "map display mode under Windows", 20, DISP_IN_GAME },	/*WC*/
240.  	{ "menustyle", "user interface for object selection",
241.  						MENUTYPELEN, SET_IN_GAME },
242.  	{ "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
243.  	{ "menu_deselect_page", "deselect all items on this page of a menu",
244.  						4, SET_IN_FILE },
245.  	{ "menu_first_page", "jump to the first page in a menu",
246.  						4, SET_IN_FILE },
247.  	{ "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
248.  	{ "menu_invert_page", "invert all items on this page of a menu",
249.  						4, SET_IN_FILE },
250.  	{ "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
251.  	{ "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
252.  	{ "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
253.  	{ "menu_search", "search for a menu item", 4, SET_IN_FILE },
254.  	{ "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
255.  	{ "menu_select_page", "select all items on this page of a menu",
256.  						4, SET_IN_FILE },
257.  	{ "monsters", "the symbols to use for monsters",
258.  						MAXMCLASSES, SET_IN_FILE },
259.  	{ "msghistory", "number of top line messages to save",
260.  						5, DISP_IN_GAME },
261.  	{ "name",     "your character's name (e.g., name:Merlin-W)",
262.  						PL_NSIZ, DISP_IN_GAME },
263.  	{ "objects",  "the symbols to use for objects",
264.  						MAXOCLASSES, SET_IN_FILE },
265.  	{ "packorder", "the inventory order of the items in your pack",
266.  						MAXOCLASSES, SET_IN_GAME },
267.  #ifdef CHANGE_COLOR
268.  	{ "palette",  "palette (00c/880/-fff is blue/yellow/reverse white)",
269.  						15 , SET_IN_GAME },
270.  # if defined(MAC)
271.  	{ "hicolor",  "same as palette, only order is reversed",
272.  						15, SET_IN_FILE },
273.  # endif
274.  #endif
275.  	{ "pettype",  "your preferred initial pet type", 4, DISP_IN_GAME },
276.  	{ "pickup_burden",  "maximum burden picked up before prompt",
277.  						20, SET_IN_GAME },
278.  	{ "pickup_types", "types of objects to pick up automatically",
279.  						MAXOCLASSES, SET_IN_GAME },
280.  	{ "player_selection", "choose character via dialog or prompts",
281.  						12, DISP_IN_GAME },
282.  	{ "race",     "your starting race (e.g., Human, Elf)",
283.  						PL_CSIZ, DISP_IN_GAME },
284.  	{ "role",     "your starting role (e.g., Barbarian, Valkyrie)",
285.  						PL_CSIZ, DISP_IN_GAME },
286.  	{ "scores",   "the parts of the score list you wish to see",
287.  						32, SET_IN_GAME },
288.  	{ "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
289.  #ifdef MSDOS
290.  	{ "soundcard", "type of sound card to use", 20, SET_IN_FILE },
291.  #endif
292.  	{ "suppress_alert", "suppress alerts about version-specific features",
293.  						8, SET_IN_GAME },
294.  	{ "tile_width", "width of tiles", 20, DISP_IN_GAME},	/*WC*/
295.  	{ "tile_height", "height of tiles", 20, DISP_IN_GAME},	/*WC*/
296.  	{ "tile_file", "name of tile file", 70, DISP_IN_GAME},	/*WC*/
297.  	{ "traps",    "the symbols to use in drawing traps",
298.  						MAXTCHARS+1, SET_IN_FILE },
299.  #ifdef MAC
300.  	{"use_stone", "use stone background patterns", 8, SET_IN_FILE },
301.  #endif
302.  	{ "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/
303.  #ifdef MSDOS
304.  	{ "video",    "method of video updating", 20, SET_IN_FILE },
305.  #endif
306.  #ifdef VIDEOSHADES
307.  	{ "videocolors", "color mappings for internal screen routines",
308.  						40, DISP_IN_GAME },
309.  	{ "videoshades", "gray shades to map to black/gray/white",
310.  						32, DISP_IN_GAME },
311.  #endif
312.  	{ "windowcolors",  "the foreground/background colors of windows",	/*WC*/
313.  						80, DISP_IN_GAME },
314.  	{ "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
315.  	{ (char *)0, (char *)0, 0, 0 }
316.  };
317.  
318.  #ifdef OPTION_LISTS_ONLY
319.  #undef static
320.  
321.  #else	/* use rest of file */
322.  
323.  static boolean need_redraw; /* for doset() */
324.  
325.  #if defined(TOS) && defined(TEXTCOLOR)
326.  extern boolean colors_changed;	/* in tos.c */
327.  #endif
328.  
329.  #ifdef VIDEOSHADES
330.  extern char *shade[3];		  /* in sys/msdos/video.c */
331.  extern char ttycolors[CLR_MAX];	  /* in sys/msdos/video.c */
332.  #endif
333.  
334.  static char def_inv_order[MAXOCLASSES] = {
335.  	GOLD_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
336.  	SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
337.  	TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
338.  };
339.  
340.  /*
341.   * Default menu manipulation command accelerators.  These may _not_ be:
342.   *
343.   *	+ a number - reserved for counts
344.   *	+ an upper or lower case US ASCII letter - used for accelerators
345.   *	+ ESC - reserved for escaping the menu
346.   *	+ NULL, CR or LF - reserved for commiting the selection(s).  NULL
347.   *	  is kind of odd, but the tty's xwaitforspace() will return it if
348.   *	  someone hits a <ret>.
349.   *	+ a default object class symbol - used for object class accelerators
350.   *
351.   * Standard letters (for now) are:
352.   *
353.   *		<  back 1 page
354.   *		>  forward 1 page
355.   *		^  first page
356.   *		|  last page
357.   *		:  search
358.   *
359.   *		page		all
360.   *		 ,    select	 .
361.   *		 \    deselect	 -
362.   *		 ~    invert	 @
363.   *
364.   * The command name list is duplicated in the compopt array.
365.   */
366.  typedef struct {
367.      const char *name;
368.      char cmd;
369.  } menu_cmd_t;
370.  
371.  #define NUM_MENU_CMDS 11
372.  static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
373.  /* 0*/	{ "menu_first_page",	MENU_FIRST_PAGE },
374.  	{ "menu_last_page",	MENU_LAST_PAGE },
375.  	{ "menu_next_page",	MENU_NEXT_PAGE },
376.  	{ "menu_previous_page",	MENU_PREVIOUS_PAGE },
377.  	{ "menu_select_all",	MENU_SELECT_ALL },
378.  /* 5*/	{ "menu_deselect_all",	MENU_UNSELECT_ALL },
379.  	{ "menu_invert_all",	MENU_INVERT_ALL },
380.  	{ "menu_select_page",	MENU_SELECT_PAGE },
381.  	{ "menu_deselect_page",	MENU_UNSELECT_PAGE },
382.  	{ "menu_invert_page",	MENU_INVERT_PAGE },
383.  /*10*/	{ "menu_search",		MENU_SEARCH },
384.  };
385.  
386.  /*
387.   * Allow the user to map incoming characters to various menu commands.
388.   * The accelerator list must be a valid C string.
389.   */
390.  #define MAX_MENU_MAPPED_CMDS 32	/* some number */
391.         char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1];	/* exported */
392.  static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1];
393.  static short n_menu_mapped = 0;
394.  
395.  
396.  static boolean initial, from_file;
397.  
398.  STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int));
399.  STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
400.  STATIC_DCL void FDECL(escapes, (const char *, char *));
401.  STATIC_DCL void FDECL(rejectoption, (const char *));
402.  STATIC_DCL void FDECL(badoption, (const char *));
403.  STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P));
404.  STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *,BOOLEAN_P));
405.  STATIC_DCL void FDECL(bad_negation, (const char *,BOOLEAN_P));
406.  STATIC_DCL int FDECL(change_inv_order, (char *));
407.  STATIC_DCL void FDECL(oc_to_str, (char *, char *));
408.  STATIC_DCL void FDECL(graphics_opts, (char *,const char *,int,int));
409.  STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
410.  STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
411.  STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P));
412.  STATIC_DCL void FDECL(warning_opts, (char *,const char *));
413.  STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int));
414.  
415.  STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
416.  STATIC_OVL int FDECL(wc_set_window_colors, (char *));
417.  STATIC_OVL boolean FDECL(is_wc_option, (const char *));
418.  STATIC_OVL boolean FDECL(wc_supported, (const char *));
419.  
420.  /* check whether a user-supplied option string is a proper leading
421.     substring of a particular option name; option string might have
422.     a colon or equals sign and arbitrary value appended to it */
423.  boolean
424.  match_optname(user_string, opt_name, min_length, val_allowed)
425.  const char *user_string, *opt_name;
426.  int min_length;
427.  boolean val_allowed;
428.  {
429.  	int len = (int)strlen(user_string);
430.  
431.  	if (val_allowed) {
432.  	    const char *p = index(user_string, ':'),
433.  		       *q = index(user_string, '=');
434.  
435.  	    if (!p || (q && q < p)) p = q;
436.  	    while(p && p > user_string && isspace(*(p-1))) p--;
437.  	    if (p) len = (int)(p - user_string);
438.  	}
439.  
440.  	return (len >= min_length) && !strncmpi(opt_name, user_string, len);
441.  }
442.  
443.  /* most environment variables will eventually be printed in an error
444.   * message if they don't work, and most error message paths go through
445.   * BUFSZ buffers, which could be overflowed by a maliciously long
446.   * environment variable.  if a variable can legitimately be long, or
447.   * if it's put in a smaller buffer, the responsible code will have to
448.   * bounds-check itself.
449.   */
450.  char *
451.  nh_getenv(ev)
452.  const char *ev;
453.  {
454.  	char *getev = getenv(ev);
455.  
456.  	if (getev && strlen(getev) <= (BUFSZ / 2))
457.  		return getev;
458.  	else
459.  		return (char *)0;
460.  }
461.  
462.  void
463.  initoptions()
464.  {
465.  	char *opts;
466.  	int i;
467.  
468.  	/* initialize the random number generator */
469.  	setrandom();
470.  
471.  	/* for detection of configfile options specified multiple times */
472.  	iflags.opt_booldup = iflags.opt_compdup = (int *)0;
473.  	
474.  	for (i = 0; boolopt[i].name; i++) {
475.  		if (boolopt[i].addr)
476.  			*(boolopt[i].addr) = boolopt[i].initvalue;
477.  	}
478.  	flags.end_own = FALSE;
479.  	flags.end_top = 3;
480.  	flags.end_around = 2;
481.  	iflags.msg_history = 20;
482.  
483.  	/* Use negative indices to indicate not yet selected */
484.  	flags.initrole = -1;
485.  	flags.initrace = -1;
486.  	flags.initgend = -1;
487.  	flags.initalign = -1;
488.  
489.  	/* Set the default monster and object class symbols.  Don't use */
490.  	/* memcpy() --- sizeof char != sizeof uchar on some machines.	*/
491.  	for (i = 0; i < MAXOCLASSES; i++)
492.  		oc_syms[i] = (uchar) def_oc_syms[i];
493.  	for (i = 0; i < MAXMCLASSES; i++)
494.  		monsyms[i] = (uchar) def_monsyms[i];
495.  	for (i = 0; i < WARNCOUNT; i++)
496.  		warnsyms[i] = def_warnsyms[i].sym;
497.  	iflags.bouldersym = 0;
498.  	flags.warnlevel = 1;
499.  	flags.warntype = 0L;
500.  
501.       /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
502.  	(void)memcpy((genericptr_t)flags.inv_order,
503.  		     (genericptr_t)def_inv_order, sizeof flags.inv_order);
504.  	flags.pickup_types[0] = '\0';
505.  	flags.pickup_burden = MOD_ENCUMBER;
506.  
507.  	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
508.  		flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
509.  	switch_graphics(ASCII_GRAPHICS);	/* set default characters */
510.  #if defined(UNIX) && defined(TTY_GRAPHICS)
511.  	/*
512.  	 * Set defaults for some options depending on what we can
513.  	 * detect about the environment's capabilities.
514.  	 * This has to be done after the global initialization above
515.  	 * and before reading user-specific initialization via
516.  	 * config file/environment variable below.
517.  	 */
518.  	/* this detects the IBM-compatible console on most 386 boxes */
519.  	if (!strncmp(nh_getenv("TERM"), "AT", 2)) {
520.  		switch_graphics(IBM_GRAPHICS);
521.  # ifdef TEXTCOLOR
522.  		iflags.use_color = TRUE;
523.  # endif
524.  	}
525.  #endif /* UNIX && TTY_GRAPHICS */
526.  #if defined(UNIX) || defined(VMS)
527.  # ifdef TTY_GRAPHICS
528.  	/* detect whether a "vt" terminal can handle alternate charsets */
529.  	if (!strncmpi(nh_getenv("TERM"), "vt", 2) && (AS && AE) &&
530.  	    index(AS, '\016') && index(AE, '\017')) {
531.  		switch_graphics(DEC_GRAPHICS);
532.  	}
533.  # endif
534.  #endif /* UNIX || VMS */
535.  
536.  #ifdef MAC_GRAPHICS_ENV
537.  	switch_graphics(MAC_GRAPHICS);
538.  #endif /* MAC_GRAPHICS_ENV */
539.  	flags.menu_style = MENU_FULL;
540.  
541.  	/* since this is done before init_objects(), do partial init here */
542.  	objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
543.  	nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
544.  #ifndef MAC
545.  	opts = getenv("NETHACKOPTIONS");
546.  	if (!opts) opts = getenv("HACKOPTIONS");
547.  	if (opts) {
548.  		if (*opts == '/' || *opts == '\\' || *opts == '@') {
549.  			if (*opts == '@') opts++;	/* @filename */
550.  			/* looks like a filename */
551.  			if (strlen(opts) < BUFSZ/2)
552.  			    read_config_file(opts);
553.  		} else {
554.  			read_config_file((char *)0);
555.  			/* let the total length of options be long;
556.  			 * parseoptions() will check each individually
557.  			 */
558.  			parseoptions(opts, TRUE, FALSE);
559.  		}
560.  	} else
561.  #endif
562.  		read_config_file((char *)0);
563.  
564.  	(void)fruitadd(pl_fruit);
565.  	/* Remove "slime mold" from list of object names; this will	*/
566.  	/* prevent it from being wished unless it's actually present	*/
567.  	/* as a named (or default) fruit.  Wishing for "fruit" will	*/
568.  	/* result in the player's preferred fruit [better than "\033"].	*/
569.  	obj_descr[SLIME_MOLD].oc_name = "fruit";
570.  
571.  	return;
572.  }
573.  
574.  STATIC_OVL void
575.  nmcpy(dest, src, maxlen)
576.  	char	*dest;
577.  	const char *src;
578.  	int	maxlen;
579.  {
580.  	int	count;
581.  
582.  	for(count = 1; count < maxlen; count++) {
583.  		if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
584.  		*dest++ = *src++;
585.  	}
586.  	*dest = 0;
587.  }
588.  
589.  /*
590.   * escapes: escape expansion for showsyms. C-style escapes understood include
591.   * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
592.   * for control characters is also understood, and \[mM] followed by any of the
593.   * previous forms or by a character has the effect of 'meta'-ing the value (so
594.   * that the alternate character set will be enabled).
595.   */
596.  STATIC_OVL void
597.  escapes(cp, tp)
598.  const char	*cp;
599.  char *tp;
600.  {
601.      while (*cp)
602.      {
603.  	int	cval = 0, meta = 0;
604.  
605.  	if (*cp == '\\' && index("mM", cp[1])) {
606.  		meta = 1;
607.  		cp += 2;
608.  	}
609.  	if (*cp == '\\' && index("0123456789xXoO", cp[1]))
610.  	{
611.  	    const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
612.  	    int dcount = 0;
613.  
614.  	    cp++;
615.  	    if (*cp == 'x' || *cp == 'X')
616.  		for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
617.  		    cval = (cval * 16) + (dp - hex) / 2;
618.  	    else if (*cp == 'o' || *cp == 'O')
619.  		for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
620.  		    cval = (cval * 8) + (*cp - '0');
621.  	    else
622.  		for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
623.  		    cval = (cval * 10) + (*cp - '0');
624.  	}
625.  	else if (*cp == '\\')		/* C-style character escapes */
626.  	{
627.  	    switch (*++cp)
628.  	    {
629.  	    case '\\': cval = '\\'; break;
630.  	    case 'n': cval = '\n'; break;
631.  	    case 't': cval = '\t'; break;
632.  	    case 'b': cval = '\b'; break;
633.  	    case 'r': cval = '\r'; break;
634.  	    default: cval = *cp;
635.  	    }
636.  	    cp++;
637.  	}
638.  	else if (*cp == '^')		/* expand control-character syntax */
639.  	{
640.  	    cval = (*++cp & 0x1f);
641.  	    cp++;
642.  	}
643.  	else
644.  	    cval = *cp++;
645.  	if (meta)
646.  	    cval |= 0x80;
647.  	*tp++ = cval;
648.      }
649.      *tp = '\0';
650.  }
651.  
652.  STATIC_OVL void
653.  rejectoption(optname)
654.  const char *optname;
655.  {
656.  #ifdef MICRO
657.  	pline("\"%s\" settable only from %s.", optname, configfile);
658.  #else
659.  	pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
660.  			configfile);
661.  #endif
662.  }
663.  
664.  STATIC_OVL void
665.  badoption(opts)
666.  const char *opts;
667.  {
668.  	if (!initial) {
669.  	    if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
670.  		option_help();
671.  	    else
672.  		pline("Bad syntax: %s.  Enter \"?g\" for help.", opts);
673.  	    return;
674.  	}
675.  #ifdef MAC
676.  	else return;
677.  #endif
678.  
679.  	if(from_file)
680.  	    raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
681.  	else
682.  	    raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts);
683.  
684.  	wait_synch();
685.  }
686.  
687.  STATIC_OVL char *
688.  string_for_opt(opts, val_optional)
689.  char *opts;
690.  boolean val_optional;
691.  {
692.  	char *colon, *equals;
693.  
694.  	colon = index(opts, ':');
695.  	equals = index(opts, '=');
696.  	if (!colon || (equals && equals < colon)) colon = equals;
697.  
698.  	if (!colon || !*++colon) {
699.  		if (!val_optional) badoption(opts);
700.  		return (char *)0;
701.  	}
702.  	return colon;
703.  }
704.  
705.  STATIC_OVL char *
706.  string_for_env_opt(optname, opts, val_optional)
707.  const char *optname;
708.  char *opts;
709.  boolean val_optional;
710.  {
711.  	if(!initial) {
712.  		rejectoption(optname);
713.  		return (char *)0;
714.  	}
715.  	return string_for_opt(opts, val_optional);
716.  }
717.  
718.  STATIC_OVL void
719.  bad_negation(optname, with_parameter)
720.  const char *optname;
721.  boolean with_parameter;
722.  {
723.  	pline_The("%s option may not %sbe negated.",
724.  		optname,
725.  		with_parameter ? "both have a value and " : "");
726.  }
727.  
728.  /*
729.   * Change the inventory order, using the given string as the new order.
730.   * Missing characters in the new order are filled in at the end from
731.   * the current inv_order, except for gold, which is forced to be first
732.   * if not explicitly present.
733.   *
734.   * This routine returns 1 unless there is a duplicate or bad char in
735.   * the string.
736.   */
737.  STATIC_OVL int
738.  change_inv_order(op)
739.  char *op;
740.  {
741.      int oc_sym, num;
742.      char *sp, buf[BUFSZ];
743.  
744.      num = 0;
745.  #ifndef GOLDOBJ
746.      if (!index(op, GOLD_SYM))
747.  	buf[num++] = GOLD_CLASS;
748.  #else
749.      /*  !!!! probably unnecessary with gold as normal inventory */
750.  #endif
751.  
752.      for (sp = op; *sp; sp++) {
753.  	oc_sym = def_char_to_objclass(*sp);
754.  	/* reject bad or duplicate entries */
755.  	if (oc_sym == MAXOCLASSES ||
756.  		oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS ||
757.  		!index(flags.inv_order, oc_sym) || index(sp+1, *sp))
758.  	    return 0;
759.  	/* retain good ones */
760.  	buf[num++] = (char) oc_sym;
761.      }
762.      buf[num] = '\0';
763.  
764.      /* fill in any omitted classes, using previous ordering */
765.      for (sp = flags.inv_order; *sp; sp++)
766.  	if (!index(buf, *sp)) {
767.  	    buf[num++] = *sp;
768.  	    buf[num] = '\0';	/* explicitly terminate for next index() */
769.  	}
770.  
771.      Strcpy(flags.inv_order, buf);
772.      return 1;
773.  }
774.  
775.  STATIC_OVL void
776.  graphics_opts(opts, optype, maxlen, offset)
777.  register char *opts;
778.  const char *optype;
779.  int maxlen, offset;
780.  {
781.  	uchar translate[MAXPCHARS+1];
782.  	int length, i;
783.  
784.  	if (!(opts = string_for_env_opt(optype, opts, FALSE)))
785.  		return;
786.  	escapes(opts, opts);
787.  
788.  	length = strlen(opts);
789.  	if (length > maxlen) length = maxlen;
790.  	/* match the form obtained from PC configuration files */
791.  	for (i = 0; i < length; i++)
792.  		translate[i] = (uchar) opts[i];
793.  	assign_graphics(translate, length, maxlen, offset);
794.  }
795.  
796.  STATIC_OVL void
797.  warning_opts(opts, optype)
798.  register char *opts;
799.  const char *optype;
800.  {
801.  	uchar translate[MAXPCHARS+1];
802.  	int length, i;
803.  
804.  	if (!(opts = string_for_env_opt(optype, opts, FALSE)))
805.  		return;
806.  	escapes(opts, opts);
807.  
808.  	length = strlen(opts);
809.  	if (length > WARNCOUNT) length = WARNCOUNT;
810.  	/* match the form obtained from PC configuration files */
811.  	for (i = 0; i < length; i++)
812.  	     translate[i] = (((i < WARNCOUNT) && opts[i]) ?
813.  			   (uchar) opts[i] : def_warnsyms[i].sym);
814.  	assign_warnings(translate);
815.  }
816.  
817.  void
818.  assign_warnings(graph_chars)
819.  register uchar *graph_chars;
820.  {
821.  	int i;
822.  	for (i = 0; i < WARNCOUNT; i++)
823.  	    warnsyms[i] = graph_chars[i];
824.  }
825.  
826.  STATIC_OVL int
827.  feature_alert_opts(op, optn)
828.  char *op;
829.  const char *optn;
830.  {
831.  	char buf[BUFSZ];
832.  	boolean rejectver = FALSE;
833.  	unsigned long fnv = get_feature_notice_ver(op);		/* version.c */
834.  	if (fnv == 0L) return 0;
835.  	if (fnv > get_current_feature_ver())
836.  		rejectver = TRUE;
837.  	else
838.  		flags.suppress_alert = fnv;
839.  	if (rejectver) {
840.  		if (!initial)
841.  			You_cant("disable new feature alerts for future versions.");
842.  		else {
843.  			Sprintf(buf,
844.  				"\n%s=%s Invalid reference to a future version ignored",
845.  				optn, op);
846.  			badoption(buf);
847.  		}
848.  		return 0;
849.  	}
850.  	if (!initial) {
851.  		Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
852.  			FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
853.  		pline("Feature change alerts disabled for NetHack %s features and prior.",
854.  			buf);
855.  	}
856.  	return 1;
857.  }
858.  
859.  void
860.  set_duplicate_opt_detection(on_or_off)
861.  int on_or_off;
862.  {
863.  	int k, *optptr;
864.  	if (on_or_off != 0) {
865.  		/*-- ON --*/
866.  		if (iflags.opt_booldup)
867.  			impossible("iflags.opt_booldup already on (memory leak)");
868.  		iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int));
869.  		optptr = iflags.opt_booldup;
870.  		for (k = 0; k < SIZE(boolopt); ++k)
871.  			*optptr++ = 0;
872.  			
873.  		if (iflags.opt_compdup)
874.  			impossible("iflags.opt_compdup already on (memory leak)");
875.  		iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int));
876.  		optptr = iflags.opt_compdup;
877.  		for (k = 0; k < SIZE(compopt); ++k)
878.  			*optptr++ = 0;
879.  	} else {
880.  		/*-- OFF --*/
881.  		if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup);
882.  		iflags.opt_booldup = (int *)0;
883.  		if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup);
884.  		iflags.opt_compdup = (int *)0;
885.  	} 
886.  }
887.  
888.  STATIC_OVL void
889.  duplicate_opt_detection(opts, bool_or_comp)
890.  const char *opts;
891.  int bool_or_comp;	/* 0 == boolean option, 1 == compound */
892.  {
893.  	int i, *optptr;
894.  #if defined(MAC)
895.  	/* the Mac has trouble dealing with the output of messages while
896.  	 * processing the config file.  That should get fixed one day.
897.  	 * For now just return.
898.  	 */
899.  	return;
900.  #endif
901.  	if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) {
902.  	    for (i = 0; boolopt[i].name; i++) {
903.  		if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
904.  			optptr = iflags.opt_booldup + i;
905.  			if (*optptr == 1) {
906.  			    raw_printf(
907.  				"\nWarning - Boolean option specified multiple times: %s.\n",
908.  					opts);
909.  			        wait_synch();
910.  			}
911.  			*optptr += 1;
912.  			break; /* don't match multiple options */
913.  		}
914.  	    }
915.  	} else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) {
916.  	    for (i = 0; compopt[i].name; i++) {
917.  		if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) {
918.  			optptr = iflags.opt_compdup + i;
919.  			if (*optptr == 1) {
920.  			    raw_printf(
921.  				"\nWarning - compound option specified multiple times: %s.\n",
922.  					compopt[i].name);
923.  			        wait_synch();
924.  			}
925.  			*optptr += 1;
926.  			break; /* don't match multiple options */
927.  		}
928.  	    }
929.  	}
930.  }
931.  
932.  void
933.  parseoptions(opts, tinitial, tfrom_file)
934.  register char *opts;
935.  boolean tinitial, tfrom_file;
936.  {
937.  	register char *op;
938.  	unsigned num;
939.  	boolean negated;
940.  	int i;
941.  	const char *fullname;
942.  
943.  	initial = tinitial;
944.  	from_file = tfrom_file;
945.  	if ((op = index(opts, ',')) != 0) {
946.  		*op++ = 0;
947.  		parseoptions(op, initial, from_file);
948.  	}
949.  	if (strlen(opts) > BUFSZ/2) {
950.  		badoption("option too long");
951.  		return;
952.  	}
953.  
954.  	/* strip leading and trailing white space */
955.  	while (isspace(*opts)) opts++;
956.  	op = eos(opts);
957.  	while (--op >= opts && isspace(*op)) *op = '\0';
958.  
959.  	if (!*opts) return;
960.  	negated = FALSE;
961.  	while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
962.  		if (*opts == '!') opts++; else opts += 2;
963.  		negated = !negated;
964.  	}
965.  
966.  	/* variant spelling */
967.  
968.  	if (match_optname(opts, "colour", 5, FALSE))
969.  		Strcpy(opts, "color");	/* fortunately this isn't longer */
970.  
971.  	duplicate_opt_detection(opts, 1);	/* 1 means compound opts */
972.  
973.  	/* special boolean options */
974.  
975.  	if (match_optname(opts, "female", 3, FALSE)) {
976.  		if(!initial && flags.female == negated)
977.  			pline("That is not anatomically possible.");
978.  		else
979.  			flags.initgend = flags.female = !negated;
980.  		return;
981.  	}
982.  
983.  	if (match_optname(opts, "male", 4, FALSE)) {
984.  		if(!initial && flags.female != negated)
985.  			pline("That is not anatomically possible.");
986.  		else
987.  			flags.initgend = flags.female = negated;
988.  		return;
989.  	}
990.  
991.  #if defined(MICRO) && !defined(AMIGA)
992.  	/* included for compatibility with old NetHack.cnf files */
993.  	if (match_optname(opts, "IBM_", 4, FALSE)) {
994.  		iflags.BIOS = !negated;
995.  		return;
996.  	}
997.  #endif /* MICRO */
998.  
999.  	/* compound options */
1000. 
1001. 	fullname = "pettype";
1002. 	if (match_optname(opts, fullname, 3, TRUE)) {
1003. 		if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
1004. 		    if (negated) bad_negation(fullname, TRUE);
1005. 		    else switch (*op) {
1006. 			case 'd':	/* dog */
1007. 			case 'D':
1008. 			    preferred_pet = 'd';
1009. 			    break;
1010. 			case 'c':	/* cat */
1011. 			case 'C':
1012. 			case 'f':	/* feline */
1013. 			case 'F':
1014. 			    preferred_pet = 'c';
1015. 			    break;
1016. 			case 'n':	/* no pet */
1017. 			case 'N':
1018. 			    preferred_pet = 'n';
1019. 			    break;
1020. 			default:
1021. 			    pline("Unrecognized pet type '%s'", op);
1022. 			    break;
1023. 		    }
1024. 		} else if (negated) preferred_pet = 'n';
1025. 		return;
1026. 	}
1027. 
1028. 	fullname = "catname";
1029. 	if (match_optname(opts, fullname, 3, TRUE)) {
1030. 		if (negated) bad_negation(fullname, FALSE);
1031. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1032. 			nmcpy(catname, op, PL_PSIZ);
1033. 		return;
1034. 	}
1035. 
1036. 	fullname = "dogname";
1037. 	if (match_optname(opts, fullname, 3, TRUE)) {
1038. 		if (negated) bad_negation(fullname, FALSE);
1039. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1040. 			nmcpy(dogname, op, PL_PSIZ);
1041. 		return;
1042. 	}
1043. 
1044. 	fullname = "horsename";
1045. 	if (match_optname(opts, fullname, 5, TRUE)) {
1046. 		if (negated) bad_negation(fullname, FALSE);
1047. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1048. 			nmcpy(horsename, op, PL_PSIZ);
1049. 		return;
1050. 	}
1051. 
1052. 	fullname = "msghistory";
1053. 	if (match_optname(opts, fullname, 3, TRUE)) {
1054. 		op = string_for_env_opt(fullname, opts, negated);
1055. 		if ((negated && !op) || (!negated && op)) {
1056. 			iflags.msg_history = negated ? 0 : atoi(op);
1057. 		} else if (negated) bad_negation(fullname, TRUE);
1058. 		return;
1059. 	}
1060. 
1061. 	/* WINCAP
1062. 	 * setting font options  */
1063. 	fullname = "font";
1064. 	if (!strncmpi(opts, fullname, 4))
1065. 	{
1066. 		int wintype = -1;
1067. 		char *fontopts = opts + 4;
1068. 
1069. 		if (!strncmpi(fontopts, "map", 3) ||
1070. 		    !strncmpi(fontopts, "_map", 4))
1071. 			wintype = NHW_MAP;
1072. 		else if (!strncmpi(fontopts, "message", 7) ||
1073. 			 !strncmpi(fontopts, "_message", 8))
1074. 			wintype = NHW_MESSAGE;
1075. 		else if (!strncmpi(fontopts, "text", 4) ||
1076. 			 !strncmpi(fontopts, "_text", 5))
1077. 			wintype = NHW_TEXT;			
1078. 		else if (!strncmpi(fontopts, "menu", 4) ||
1079. 			 !strncmpi(fontopts, "_menu", 5))
1080. 			wintype = NHW_MENU;
1081. 		else if (!strncmpi(fontopts, "status", 6) ||
1082. 			 !strncmpi(fontopts, "_status", 7))
1083. 			wintype = NHW_STATUS;
1084. 		else if (!strncmpi(fontopts, "_size", 5)) {
1085. 			if (!strncmpi(fontopts, "_size_map", 8))
1086. 				wintype = NHW_MAP;
1087. 			else if (!strncmpi(fontopts, "_size_message", 12))
1088. 				wintype = NHW_MESSAGE;
1089. 			else if (!strncmpi(fontopts, "_size_text", 9))
1090. 				wintype = NHW_TEXT;
1091. 			else if (!strncmpi(fontopts, "_size_menu", 9))
1092. 				wintype = NHW_MENU;
1093. 			else if (!strncmpi(fontopts, "_size_status", 11))
1094. 				wintype = NHW_STATUS;
1095. 			else {
1096. 				badoption(opts);
1097. 				return;
1098. 			}
1099. 			if (wintype > 0 && !negated &&
1100. 			    (op = string_for_opt(opts, FALSE)) != 0) {
1101. 			    switch(wintype)  {
1102. 			    	case NHW_MAP:
1103. 					iflags.wc_fontsiz_map = atoi(op);
1104. 					break;
1105. 			    	case NHW_MESSAGE:
1106. 					iflags.wc_fontsiz_message = atoi(op);
1107. 					break;
1108. 			    	case NHW_TEXT:
1109. 					iflags.wc_fontsiz_text = atoi(op);
1110. 					break;
1111. 			    	case NHW_MENU:
1112. 					iflags.wc_fontsiz_menu = atoi(op);
1113. 					break;
1114. 			    	case NHW_STATUS:
1115. 					iflags.wc_fontsiz_status = atoi(op);
1116. 					break;
1117. 			    }
1118. 			}
1119. 			return;
1120. 		} else {
1121. 			badoption(opts);
1122. 		}
1123. 		if (wintype > 0 &&
1124. 		    (op = string_for_opt(opts, FALSE)) != 0) {
1125. 			wc_set_font_name(wintype, op);
1126. #ifdef MAC
1127. 			set_font_name (wintype, op);
1128. #endif
1129. 			return;
1130. 		} else if (negated) bad_negation(fullname, TRUE);
1131. 		return;
1132. 	}
1133. #ifdef CHANGE_COLOR
1134. #ifdef MAC
1135. 	fullname = "use_stone";
1136. 	if (match_optname(opts, fullname, 6, TRUE)) {
1137. 		op = string_for_env_opt(fullname, opts, negated);
1138. 		if ((negated && !op) || (!negated && op)) {
1139. 			iflags.use_stone = negated ? 0 : atoi(op);
1140. 		} else if (negated) bad_negation(fullname, TRUE);
1141. 		return;
1142. 	}
1143. 
1144. 	fullname = "background";
1145. 	if (match_optname(opts, fullname, 5,TRUE))
1146. 	{
1147. 		if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1148. 		{
1149. 			if (!strncmpi (op, "white", 5))
1150. 				change_background (1);
1151. 			else if (!strncmpi (op, "black", 5))
1152. 				change_background (0);
1153. 		}
1154. 		return;
1155. 	}
1156. #endif	
1157. 
1158. 	if (match_optname(opts, "palette", 3, TRUE)
1159. # ifdef MAC
1160. 	    || match_optname(opts, "hicolor", 3, TRUE)
1161. # endif
1162. 							) {
1163. 	    int color_number, color_incr;
1164. 
1165. # ifdef MAC
1166. 	    if (match_optname(opts, "hicolor", 3, TRUE)) {
1167. 		if (negated) {
1168. 		    bad_negation("hicolor", FALSE);
1169. 		    return;
1170. 		}
1171. 		color_number = CLR_MAX + 4;	/* HARDCODED inverse number */
1172. 		color_incr = -1;
1173. 	    } else {
1174. # endif
1175. 		if (negated) {
1176. 		    bad_negation("palette", FALSE);
1177. 		    return;
1178. 		}
1179. 		color_number = 0;
1180. 		color_incr = 1;
1181. # ifdef MAC
1182. 	    }
1183. # endif
1184. 	    if ((op = string_for_opt(opts, FALSE)) != (char *)0) {
1185. 		char *pt = op;
1186. 		int cnt, tmp, reverse;
1187. 		long rgb;
1188. 
1189. 		while (*pt && color_number >= 0) {
1190. 		    cnt = 3;
1191. 		    rgb = 0L;
1192. 		    if (*pt == '-') {
1193. 			reverse = 1;
1194. 			pt++;
1195. 		    } else {
1196. 			reverse = 0;
1197. 		    }
1198. 		    while (cnt-- > 0) {
1199. 			if (*pt && *pt != '/') {
1200. # ifdef AMIGA
1201. 			    rgb <<= 4;
1202. # else
1203. 			    rgb <<= 8;
1204. # endif
1205. 			    tmp = *(pt++);
1206. 			    if (isalpha(tmp)) {
1207. 				tmp = (tmp + 9) & 0xf;	/* Assumes ASCII... */
1208. 			    } else {
1209. 				tmp &= 0xf;	/* Digits in ASCII too... */
1210. 			    }
1211. # ifndef AMIGA
1212. 			    /* Add an extra so we fill f -> ff and 0 -> 00 */
1213. 			    rgb += tmp << 4;
1214. # endif
1215. 			    rgb += tmp;
1216. 			}
1217. 		    }
1218. 		    if (*pt == '/') {
1219. 			pt++;
1220. 		    }
1221. 		    change_color(color_number, rgb, reverse);
1222. 		    color_number += color_incr;
1223. 		}
1224. 	    }
1225. 	    if (!initial) {
1226. 		need_redraw = TRUE;
1227. 	    }
1228. 	    return;
1229. 	}
1230. #endif /* CHANGE_COLOR */
1231. 
1232. 	if (match_optname(opts, "fruit", 2, TRUE)) {
1233. 		char empty_str = '\0';
1234. 		op = string_for_opt(opts, negated);
1235. 		if (negated) {
1236. 		    if (op) {
1237. 			bad_negation("fruit", TRUE);
1238. 			return;
1239. 		    }
1240. 		    op = &empty_str;
1241. 		    goto goodfruit;
1242. 		}
1243. 		if (!op) return;
1244. 		if (!initial) {
1245. 		    struct fruit *f;
1246. 
1247. 		    num = 0;
1248. 		    for(f=ffruit; f; f=f->nextf) {
1249. 			if (!strcmp(op, f->fname)) goto goodfruit;
1250. 			num++;
1251. 		    }
1252. 		    if (num >= 100) {
1253. 			pline("Doing that so many times isn't very fruitful.");
1254. 			return;
1255. 		    }
1256. 		}
1257. goodfruit:
1258. 		nmcpy(pl_fruit, op, PL_FSIZ);
1259. 	/* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
1260. 		if (!*pl_fruit)
1261. 		    nmcpy(pl_fruit, "slime mold", PL_FSIZ);
1262. 		if (!initial)
1263. 		    (void)fruitadd(pl_fruit);
1264. 		/* If initial, then initoptions is allowed to do it instead
1265. 		 * of here (initoptions always has to do it even if there's
1266. 		 * no fruit option at all.  Also, we don't want people
1267. 		 * setting multiple fruits in their options.)
1268. 		 */
1269. 		return;
1270. 	}
1271. 
1272. 	/* graphics:string */
1273. 	fullname = "graphics";
1274. 	if (match_optname(opts, fullname, 2, TRUE)) {
1275. 		if (negated) bad_negation(fullname, FALSE);
1276. 		else graphics_opts(opts, fullname, MAXPCHARS, 0);
1277. 		return;
1278. 	}
1279. 	fullname = "dungeon";
1280. 	if (match_optname(opts, fullname, 2, TRUE)) {
1281. 		if (negated) bad_negation(fullname, FALSE);
1282. 		else graphics_opts(opts, fullname, MAXDCHARS, 0);
1283. 		return;
1284. 	}
1285. 	fullname = "traps";
1286. 	if (match_optname(opts, fullname, 2, TRUE)) {
1287. 		if (negated) bad_negation(fullname, FALSE);
1288. 		else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS);
1289. 		return;
1290. 	}
1291. 	fullname = "effects";
1292. 	if (match_optname(opts, fullname, 2, TRUE)) {
1293. 		if (negated) bad_negation(fullname, FALSE);
1294. 		else
1295. 		 graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS);
1296. 		return;
1297. 	}
1298. 
1299. 	/* objects:string */
1300. 	fullname = "objects";
1301. 	if (match_optname(opts, fullname, 7, TRUE)) {
1302. 		int length;
1303. 
1304. 		if (negated) {
1305. 		    bad_negation(fullname, FALSE);
1306. 		    return;
1307. 		}
1308. 		if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1309. 			return;
1310. 		escapes(opts, opts);
1311. 
1312. 		/*
1313. 		 * Override the default object class symbols.  The first
1314. 		 * object in the object class is the "random object".  I
1315. 		 * don't want to use 0 as an object class, so the "random
1316. 		 * object" is basically a place holder.
1317. 		 *
1318. 		 * The object class symbols have already been initialized in
1319. 		 * initoptions().
1320. 		 */
1321. 		length = strlen(opts);
1322. 		if (length >= MAXOCLASSES)
1323. 		    length = MAXOCLASSES-1;	/* don't count RANDOM_OBJECT */
1324. 
1325. 		for (i = 0; i < length; i++)
1326. 		    oc_syms[i+1] = (uchar) opts[i];
1327. 		return;
1328. 	}
1329. 
1330. 	/* monsters:string */
1331. 	fullname = "monsters";
1332. 	if (match_optname(opts, fullname, 8, TRUE)) {
1333. 		int length;
1334. 
1335. 		if (negated) {
1336. 		    bad_negation(fullname, FALSE);
1337. 		    return;
1338. 		}
1339. 		if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1340. 			return;
1341. 		escapes(opts, opts);
1342. 
1343. 		/* Override default mon class symbols set in initoptions(). */
1344. 		length = strlen(opts);
1345. 		if (length >= MAXMCLASSES)
1346. 		    length = MAXMCLASSES-1;	/* mon class 0 unused */
1347. 
1348. 		for (i = 0; i < length; i++)
1349. 		    monsyms[i+1] = (uchar) opts[i];
1350. 		return;
1351. 	}
1352. 	fullname = "warnings";
1353. 	if (match_optname(opts, fullname, 5, TRUE)) {
1354. 		if (negated) bad_negation(fullname, FALSE);
1355. 		else warning_opts(opts, fullname);
1356. 		return;
1357. 	}
1358. 	/* boulder:symbol */
1359. 	fullname = "boulder";
1360. 	if (match_optname(opts, fullname, 7, TRUE)) {
1361. 		if (negated) {
1362. 		    bad_negation(fullname, FALSE);
1363. 		    return;
1364. 		}
1365. /*		if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */
1366. 		if (!(opts = string_for_opt(opts, FALSE)))
1367. 			return;
1368. 		escapes(opts, opts);
1369. 
1370. 		/*
1371. 		 * Override the default boulder symbol.
1372. 		 */
1373. 		iflags.bouldersym = (uchar) opts[0];
1374. 		if (!initial) need_redraw = TRUE;
1375. 		return;
1376. 	}
1377. 
1378. 	/* name:string */
1379. 	fullname = "name";
1380. 	if (match_optname(opts, fullname, 4, TRUE)) {
1381. 		if (negated) bad_negation(fullname, FALSE);
1382. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1383. 			nmcpy(plname, op, PL_NSIZ);
1384. 		return;
1385. 	}
1386. 
1387. 	/* role:string or character:string */
1388. 	fullname = "role";
1389. 	if (match_optname(opts, fullname, 4, TRUE) ||
1390. 	    match_optname(opts, (fullname = "character"), 4, TRUE)) {
1391. 		if (negated) bad_negation(fullname, FALSE);
1392. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1393. 			if ((flags.initrole = str2role(op)) == ROLE_NONE)
1394. 				badoption(opts);
1395. 			else  /* Backwards compatibility */
1396. 				nmcpy(pl_character, op, PL_NSIZ);
1397. 		}
1398. 		return;
1399. 	}
1400. 
1401. 	/* race:string */
1402. 	fullname = "race";
1403. 	if (match_optname(opts, fullname, 4, TRUE)) {
1404. 		if (negated) bad_negation(fullname, FALSE);
1405. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1406. 			if ((flags.initrace = str2race(op)) == ROLE_NONE)
1407. 				badoption(opts);
1408. 			else /* Backwards compatibility */
1409. 				pl_race = *op;
1410. 		}
1411. 		return;
1412. 	}
1413. 
1414. 	/* gender:string */
1415. 	fullname = "gender";
1416. 	if (match_optname(opts, fullname, 4, TRUE)) {
1417. 		if (negated) bad_negation(fullname, FALSE);
1418. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1419. 			if ((flags.initgend = str2gend(op)) == ROLE_NONE)
1420. 				badoption(opts);
1421. 			else
1422. 				flags.female = flags.initgend;
1423. 		}
1424. 		return;
1425. 	}
1426. 
1427. 	/* WINCAP
1428. 	 * align_status:[left|top|right|bottom] */
1429. 	fullname = "align_status";
1430. 	if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) {
1431. 		op = string_for_opt(opts, negated);
1432. 		if (op && !negated) {
1433. 		    if (!strncmpi (op, "left", sizeof("left")-1))
1434. 			iflags.wc_align_status = ALIGN_LEFT;
1435. 		    else if (!strncmpi (op, "top", sizeof("top")-1))
1436. 			iflags.wc_align_status = ALIGN_TOP;
1437. 		    else if (!strncmpi (op, "right", sizeof("right")-1))
1438. 			iflags.wc_align_status = ALIGN_RIGHT;
1439. 		    else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1440. 			iflags.wc_align_status = ALIGN_BOTTOM;
1441. 		    else
1442. 			badoption(opts);
1443. 		} else if (negated) bad_negation(fullname, TRUE);
1444. 		return;
1445. 	}
1446. 	/* WINCAP
1447. 	 * align_message:[left|top|right|bottom] */
1448. 	fullname = "align_message";
1449. 	if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) {
1450. 		op = string_for_opt(opts, negated);
1451. 		if (op && !negated) {
1452. 		    if (!strncmpi (op, "left", sizeof("left")-1))
1453. 			iflags.wc_align_message = ALIGN_LEFT;
1454. 		    else if (!strncmpi (op, "top", sizeof("top")-1))
1455. 			iflags.wc_align_message = ALIGN_TOP;
1456. 		    else if (!strncmpi (op, "right", sizeof("right")-1))
1457. 			iflags.wc_align_message = ALIGN_RIGHT;
1458. 		    else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1459. 			iflags.wc_align_message = ALIGN_BOTTOM;
1460. 		    else
1461. 			badoption(opts);
1462. 		} else if (negated) bad_negation(fullname, TRUE);
1463. 		return;
1464. 	}
1465. 	/* align:string */
1466. 	fullname = "align";
1467. 	if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) {
1468. 		if (negated) bad_negation(fullname, FALSE);
1469. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1470. 			if ((flags.initalign = str2align(op)) == ROLE_NONE)
1471. 				badoption(opts);
1472. 		return;
1473. 	}
1474. 
1475. 	/* the order to list the pack */
1476. 	fullname = "packorder";
1477. 	if (match_optname(opts, fullname, 4, TRUE)) {
1478. 		if (negated) {
1479. 		    bad_negation(fullname, FALSE);
1480. 		    return;
1481. 		} else if (!(op = string_for_opt(opts, FALSE))) return;
1482. 
1483. 		if (!change_inv_order(op))
1484. 			badoption(opts);
1485. 		return;
1486. 	}
1487. 
1488. 	/* maximum burden picked up before prompt (Warren Cheung) */
1489. 	fullname = "pickup_burden";
1490. 	if (match_optname(opts, fullname, 8, TRUE)) {
1491. 		if (negated) {
1492. 			bad_negation(fullname, FALSE);
1493. 			return;
1494. 		} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1495. 		    switch (tolower(*op)) {
1496. 				/* Unencumbered */
1497. 				case 'u':
1498. 					flags.pickup_burden = UNENCUMBERED;
1499. 					break;
1500. 				/* Burdened (slight encumbrance) */
1501. 				case 'b':
1502. 					flags.pickup_burden = SLT_ENCUMBER;
1503. 					break;
1504. 				/* streSsed (moderate encumbrance) */
1505. 				case 's':
1506. 					flags.pickup_burden = MOD_ENCUMBER;
1507. 					break;
1508. 				/* straiNed (heavy encumbrance) */
1509. 				case 'n':
1510. 					flags.pickup_burden = HVY_ENCUMBER;
1511. 					break;
1512. 				/* OverTaxed (extreme encumbrance) */
1513. 				case 'o':
1514. 				case 't':
1515. 					flags.pickup_burden = EXT_ENCUMBER;
1516. 					break;
1517. 				/* overLoaded */
1518. 				case 'l':
1519. 					flags.pickup_burden = OVERLOADED;
1520. 					break;
1521. 				default:
1522. 				badoption(opts);
1523. 		    }
1524. 		}
1525. 		return;
1526. 	}
1527. 
1528. 	/* types of objects to pick up automatically */
1529. 	if (match_optname(opts, "pickup_types", 8, TRUE)) {
1530. 		char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
1531. 		     qbuf[QBUFSZ], abuf[BUFSZ];
1532. 		int oc_sym;
1533. 		boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
1534. 
1535. 		oc_to_str(flags.pickup_types, tbuf);
1536. 		flags.pickup_types[0] = '\0';	/* all */
1537. 		op = string_for_opt(opts, (compat || !initial));
1538. 		if (!op) {
1539. 		    if (compat || negated || initial) {
1540. 			/* for backwards compatibility, "pickup" without a
1541. 			   value is a synonym for autopickup of all types
1542. 			   (and during initialization, we can't prompt yet) */
1543. 			flags.pickup = !negated;
1544. 			return;
1545. 		    }
1546. 		    oc_to_str(flags.inv_order, ocl);
1547. 		    use_menu = TRUE;
1548. 		    if (flags.menu_style == MENU_TRADITIONAL ||
1549. 			    flags.menu_style == MENU_COMBINATION) {
1550. 			use_menu = FALSE;
1551. 			Sprintf(qbuf, "New pickup_types: [%s am] (%s)",
1552. 				ocl, *tbuf ? tbuf : "all");
1553. 			getlin(qbuf, abuf);
1554. 			op = mungspaces(abuf);
1555. 			if (abuf[0] == '\0' || abuf[0] == '\033')
1556. 			    op = tbuf;		/* restore */
1557. 			else if (abuf[0] == 'm')
1558. 			    use_menu = TRUE;
1559. 		    }
1560. 		    if (use_menu) {
1561. 			(void) choose_classes_menu("Auto-Pickup what?", 1,
1562. 						   TRUE, ocl, tbuf);
1563. 			op = tbuf;
1564. 		    }
1565. 		}
1566. 		if (negated) {
1567. 		    bad_negation("pickup_types", TRUE);
1568. 		    return;
1569. 		}
1570. 		while (*op == ' ') op++;
1571. 		if (*op != 'a' && *op != 'A') {
1572. 		    num = 0;
1573. 		    while (*op) {
1574. 			oc_sym = def_char_to_objclass(*op);
1575. 			/* make sure all are valid obj symbols occuring once */
1576. 			if (oc_sym != MAXOCLASSES &&
1577. 			    !index(flags.pickup_types, oc_sym)) {
1578. 			    flags.pickup_types[num] = (char)oc_sym;
1579. 			    flags.pickup_types[++num] = '\0';
1580. 			} else
1581. 			    badopt = TRUE;
1582. 			op++;
1583. 		    }
1584. 		    if (badopt) badoption(opts);
1585. 		}
1586. 		return;
1587. 	}
1588. 	/* WINCAP
1589. 	 * player_selection: dialog | prompts */
1590. 	fullname = "player_selection";
1591. 	if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) {
1592. 		op = string_for_opt(opts, negated);
1593. 		if (op && !negated) {
1594. 		    if (!strncmpi (op, "dialog", sizeof("dialog")-1))
1595. 			iflags.wc_player_selection = VIA_DIALOG;
1596. 		    else if (!strncmpi (op, "prompt", sizeof("prompt")-1))
1597. 			iflags.wc_player_selection = VIA_PROMPTS;
1598. 		    else
1599. 		    	badoption(opts);
1600. 		} else if (negated) bad_negation(fullname, TRUE);
1601. 		return;
1602. 	}
1603. 
1604. 	/* things to disclose at end of game */
1605. 	if (match_optname(opts, "disclose", 7, TRUE)) {
1606. 		/*
1607. 		 * The order that the end_disclore options are stored:
1608. 		 * inventory, attribs, vanquished, genocided, conduct
1609. 		 * There is an array in flags:
1610. 		 *	end_disclose[NUM_DISCLOSURE_OPT];
1611. 		 * with option settings for the each of the following:
1612. 		 * iagvc [see disclosure_options in decl.c]:
1613. 		 * Legal setting values in that array are:
1614. 		 *	DISCLOSE_PROMPT_DEFAULT_YES  ask with default answer yes
1615. 		 *	DISCLOSE_PROMPT_DEFAULT_NO   ask with default answer no
1616. 		 *	DISCLOSE_YES_WITHOUT_PROMPT  always disclose and don't ask
1617. 		 *	DISCLOSE_NO_WITHOUT_PROMPT   never disclose and don't ask
1618. 		 *
1619. 		 * Those setting values can be used in the option
1620. 		 * string as a prefix to get the desired behaviour.
1621. 		 *
1622. 		 * For backward compatibility, no prefix is required,
1623. 		 * and the presence of a i,a,g,v, or c without a
1624. 		 * prefix sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT;
1625. 		 */
1626. 		boolean badopt = FALSE;
1627. 		int idx, prefix_val;
1628. 		if (!(op = string_for_opt(opts, TRUE))) {
1629. 			/* for backwards compatibility, "disclose" without a
1630. 			 * value means all (was inventory and attributes,
1631. 			 * the only things available then), but negated
1632. 			 * it means "none"
1633. 			 * (note "none" contains none of "iavkgc")
1634. 			 */
1635. 			for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++) {
1636. 				if (negated)
1637. 				    flags.end_disclose[num] = DISCLOSE_NO_WITHOUT_PROMPT;
1638. 			 	else flags.end_disclose[num] = DISCLOSE_PROMPT_DEFAULT_YES;
1639. 			}
1640. 			return;
1641. 		}
1642. 		if (negated) {
1643. 			bad_negation("disclose", TRUE);
1644. 			return;
1645. 		}
1646. 		num = 0;
1647. 		prefix_val = -1;
1648. 		while (*op && num < sizeof flags.end_disclose - 1) {
1649. 			register char c, *dop;
1650. 			static char valid_settings[] = {
1651. 				DISCLOSE_PROMPT_DEFAULT_YES,
1652. 				DISCLOSE_PROMPT_DEFAULT_NO,
1653. 				DISCLOSE_YES_WITHOUT_PROMPT,
1654. 				DISCLOSE_NO_WITHOUT_PROMPT,
1655. 				'\0'
1656. 			};
1657. 			c = lowc(*op);
1658. 			if (c == 'k') c = 'v';	/* killed -> vanquished */
1659. 			dop = index(disclosure_options, c);
1660. 			if (dop) {
1661. 				idx = dop - disclosure_options;
1662. 				if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
1663. 				    impossible("bad disclosure index %d %c",
1664. 							idx, c);
1665. 				    continue;
1666. 				}
1667. 				if (prefix_val != -1) {
1668. 				    flags.end_disclose[idx] = prefix_val;
1669. 				    prefix_val = -1;
1670. 				} else
1671. 				    flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
1672. 			} else if (index(valid_settings, c)) {
1673. 				prefix_val = c;
1674. 			} else if (c == ' ') {
1675. 				/* do nothing */
1676. 			} else
1677. 				badopt = TRUE;				
1678. 			op++;
1679. 		}
1680. 		if (badopt) badoption(opts);
1681. 		return;
1682. 	}
1683. 
1684. 	/* scores:5t[op] 5a[round] o[wn] */
1685. 	if (match_optname(opts, "scores", 4, TRUE)) {
1686. 	    if (negated) {
1687. 		bad_negation("scores", FALSE);
1688. 		return;
1689. 	    }
1690. 	    if (!(op = string_for_opt(opts, FALSE))) return;
1691. 
1692. 	    while (*op) {
1693. 		int inum = 1;
1694. 
1695. 		if (digit(*op)) {
1696. 		    inum = atoi(op);
1697. 		    while (digit(*op)) op++;
1698. 		} else if (*op == '!') {
1699. 		    negated = !negated;
1700. 		    op++;
1701. 		}
1702. 		while (*op == ' ') op++;
1703. 
1704. 		switch (*op) {
1705. 		 case 't':
1706. 		 case 'T':  flags.end_top = inum;
1707. 			    break;
1708. 		 case 'a':
1709. 		 case 'A':  flags.end_around = inum;
1710. 			    break;
1711. 		 case 'o':
1712. 		 case 'O':  flags.end_own = !negated;
1713. 			    break;
1714. 		 default:   badoption(opts);
1715. 			    return;
1716. 		}
1717. 		while (letter(*++op) || *op == ' ') continue;
1718. 		if (*op == '/') op++;
1719. 	    }
1720. 	    return;
1721. 	}
1722. 
1723. 	fullname = "suppress_alert";
1724. 	if (match_optname(opts, fullname, 4, TRUE)) {
1725. 		op = string_for_opt(opts, negated);
1726. 		if (negated) bad_negation(fullname, FALSE);
1727. 		else if (op) (void) feature_alert_opts(op,fullname);
1728. 		return;
1729. 	}
1730. 	
1731. #ifdef VIDEOSHADES
1732. 	/* videocolors:string */
1733. 	fullname = "videocolors";
1734. 	if (match_optname(opts, fullname, 6, TRUE) ||
1735. 	    match_optname(opts, "videocolours", 10, TRUE)) {
1736. 		if (negated) {
1737. 			bad_negation(fullname, FALSE);
1738. 			return;
1739. 		}
1740. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1741. 			return;
1742. 		}
1743. 		if (!assign_videocolors(opts))
1744. 			badoption(opts);
1745. 		return;
1746. 	}
1747. 	/* videoshades:string */
1748. 	fullname = "videoshades";
1749. 	if (match_optname(opts, fullname, 6, TRUE)) {
1750. 		if (negated) {
1751. 			bad_negation(fullname, FALSE);
1752. 			return;
1753. 		}
1754. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1755. 			return;
1756. 		}
1757. 		if (!assign_videoshades(opts))
1758. 			badoption(opts);
1759. 		return;
1760. 	}
1761. #endif /* VIDEOSHADES */
1762. #ifdef MSDOS
1763. # ifdef NO_TERMS
1764. 	/* video:string -- must be after longer tests */
1765. 	fullname = "video";
1766. 	if (match_optname(opts, fullname, 5, TRUE)) {
1767. 		if (negated) {
1768. 			bad_negation(fullname, FALSE);
1769. 			return;
1770. 		}
1771. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1772. 			return;
1773. 		}
1774. 		if (!assign_video(opts))
1775. 			badoption(opts);
1776. 		return;
1777. 	}
1778. # endif /* NO_TERMS */
1779. 	/* soundcard:string -- careful not to match boolean 'sound' */
1780. 	fullname = "soundcard";
1781. 	if (match_optname(opts, fullname, 6, TRUE)) {
1782. 		if (negated) {
1783. 			bad_negation(fullname, FALSE);
1784. 			return;
1785. 		}
1786. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1787. 			return;
1788. 		}
1789. 		if (!assign_soundcard(opts))
1790. 			badoption(opts);
1791. 		return;
1792. 	}
1793. #endif /* MSDOS */
1794. 
1795. 	/* WINCAP
1796. 	 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12|
1797. 			ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */
1798. 	fullname = "map_mode";
1799. 	if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) {
1800. 		op = string_for_opt(opts, negated);
1801. 		if (op && !negated) {
1802. 		    if (!strncmpi (op, "tiles", sizeof("tiles")-1))
1803. 			iflags.wc_map_mode = MAP_MODE_TILES;
1804. 		    else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1))
1805. 			iflags.wc_map_mode = MAP_MODE_ASCII4x6;
1806. 		    else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1))
1807. 			iflags.wc_map_mode = MAP_MODE_ASCII6x8;
1808. 		    else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1))
1809. 			iflags.wc_map_mode = MAP_MODE_ASCII8x8;
1810. 		    else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1))
1811. 			iflags.wc_map_mode = MAP_MODE_ASCII16x8;
1812. 		    else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1))
1813. 			iflags.wc_map_mode = MAP_MODE_ASCII7x12;
1814. 		    else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1))
1815. 			iflags.wc_map_mode = MAP_MODE_ASCII8x12;
1816. 		    else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1))
1817. 			iflags.wc_map_mode = MAP_MODE_ASCII16x12;
1818. 		    else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1))
1819. 			iflags.wc_map_mode = MAP_MODE_ASCII12x16;
1820. 		    else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1))
1821. 			iflags.wc_map_mode = MAP_MODE_ASCII10x18;
1822. 		    else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1))
1823. 			iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
1824. 		    else
1825. 		    	badoption(opts);
1826. 		} else if (negated) bad_negation(fullname, TRUE);
1827. 		return;
1828. 	}
1829. 	/* WINCAP
1830. 	 * scroll_margin:nn */
1831. 	fullname = "scroll_margin";
1832. 	if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) {
1833. 		op = string_for_opt(opts, negated);
1834. 		if ((negated && !op) || (!negated && op)) {
1835. 			iflags.wc_scroll_margin = negated ? 5 : atoi(op);
1836. 		} else if (negated) bad_negation(fullname, TRUE);
1837. 		return;
1838. 	}
1839. 	/* WINCAP
1840. 	 * tile_width:nn */
1841. 	fullname = "tile_width";
1842. 	if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) {
1843. 		op = string_for_opt(opts, negated);
1844. 		if ((negated && !op) || (!negated && op)) {
1845. 			iflags.wc_tile_width = negated ? 0 : atoi(op);
1846. 		} else if (negated) bad_negation(fullname, TRUE);
1847. 		return;
1848. 	}
1849. 	/* WINCAP
1850. 	 * tile_file:name */
1851. 	fullname = "tile_file";
1852. 	if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) {
1853. 		if ((op = string_for_opt(opts, FALSE)) != 0) {
1854. 			if (iflags.wc_tile_file) free(iflags.wc_tile_file);
1855. 			iflags.wc_tile_file = (char *)alloc(strlen(op) + 1);
1856. 			Strcpy(iflags.wc_tile_file, op);
1857. 		}
1858. 		return;
1859. 	}
1860. 	/* WINCAP
1861. 	 * tile_height:nn */
1862. 	fullname = "tile_height";
1863. 	if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) {
1864. 		op = string_for_opt(opts, negated);
1865. 		if ((negated && !op) || (!negated && op)) {
1866. 			iflags.wc_tile_height = negated ? 0 : atoi(op);
1867. 		} else if (negated) bad_negation(fullname, TRUE);
1868. 		return;
1869. 	}
1870. 	/* WINCAP
1871. 	 * vary_msgcount:nn */
1872. 	fullname = "vary_msgcount";
1873. 	if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) {
1874. 		op = string_for_opt(opts, negated);
1875. 		if ((negated && !op) || (!negated && op)) {
1876. 			iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
1877. 		} else if (negated) bad_negation(fullname, TRUE);
1878. 		return;
1879. 	}
1880. 
1881. 	fullname = "windowtype";
1882. 	if (match_optname(opts, fullname, 3, TRUE)) {
1883. 	    if (negated) {
1884. 		bad_negation(fullname, FALSE);
1885. 		return;
1886. 	    } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1887. 		char buf[WINTYPELEN];
1888. 		nmcpy(buf, op, WINTYPELEN);
1889. 		choose_windows(buf);
1890. 	    }
1891. 	    return;
1892. 	}
1893. 
1894. 	/* WINCAP
1895. 	 * setting window colors
1896.          * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
1897.          */
1898. 	fullname = "windowcolors";
1899. 	if (match_optname(opts, fullname, 7, TRUE)) {
1900. 		if ((op = string_for_opt(opts, FALSE)) != 0) {
1901. 			if (!wc_set_window_colors(op))
1902. 				badoption(opts);
1903. 		} else if (negated) bad_negation(fullname, TRUE);
1904. 		return;
1905. 	}
1906. 
1907. 	/* menustyle:traditional or combo or full or partial */
1908. 	if (match_optname(opts, "menustyle", 4, TRUE)) {
1909. 		int tmp;
1910. 		boolean val_required = (strlen(opts) > 5 && !negated);
1911. 
1912. 		if (!(op = string_for_opt(opts, !val_required))) {
1913. 		    if (val_required) return; /* string_for_opt gave feedback */
1914. 		    tmp = negated ? 'n' : 'f';
1915. 		} else {
1916. 		    tmp = tolower(*op);
1917. 		}
1918. 		switch (tmp) {
1919. 			case 'n':	/* none */
1920. 			case 't':	/* traditional */
1921. 				flags.menu_style = MENU_TRADITIONAL;
1922. 				break;
1923. 			case 'c':	/* combo: trad.class sel+menu */
1924. 				flags.menu_style = MENU_COMBINATION;
1925. 				break;
1926. 			case 'p':	/* partial: no class menu */
1927. 				flags.menu_style = MENU_PARTIAL;
1928. 				break;
1929. 			case 'f':	/* full: class menu + menu */
1930. 				flags.menu_style = MENU_FULL;
1931. 				break;
1932. 			default:
1933. 				badoption(opts);
1934. 		}
1935. 		return;
1936. 	}
1937. 
1938. 	/* check for menu command mapping */
1939. 	for (i = 0; i < NUM_MENU_CMDS; i++) {
1940. 	    fullname = default_menu_cmd_info[i].name;
1941. 	    if (match_optname(opts, fullname, (int)strlen(fullname), TRUE)) {
1942. 		if (negated)
1943. 		    bad_negation(fullname, FALSE);
1944. 		else if ((op = string_for_opt(opts, FALSE)) != 0) {
1945. 		    int j;
1946. 		    char c, op_buf[BUFSZ];
1947. 		    boolean isbad = FALSE;
1948. 
1949. 		    escapes(op, op_buf);
1950. 		    c = *op_buf;
1951. 
1952. 		    if (c == 0 || c == '\r' || c == '\n' || c == '\033' ||
1953. 			    c == ' ' || digit(c) || (letter(c) && c != '@'))
1954. 			isbad = TRUE;
1955. 		    else	/* reject default object class symbols */
1956. 			for (j = 1; j < MAXOCLASSES; j++)
1957. 			    if (c == def_oc_syms[i]) {
1958. 				isbad = TRUE;
1959. 				break;
1960. 			    }
1961. 
1962. 		    if (isbad)
1963. 			badoption(opts);
1964. 		    else
1965. 			add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
1966. 		}
1967. 		return;
1968. 	    }
1969. 	}
1970. 
1971. 	/* OK, if we still haven't recognized the option, check the boolean
1972. 	 * options list
1973. 	 */
1974. 	for (i = 0; boolopt[i].name; i++) {
1975. 		if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1976. 			/* options that don't exist */
1977. 			if (!boolopt[i].addr) {
1978. 			    if (!initial && !negated)
1979. 				pline_The("\"%s\" option is not available.",
1980. 					boolopt[i].name);
1981. 			    return;
1982. 			}
1983. 			/* options that must come from config file */
1984. 			if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
1985. 			    rejectoption(boolopt[i].name);
1986. 			    return;
1987. 			}
1988. 
1989. 			*(boolopt[i].addr) = !negated;
1990. 
1991. 			duplicate_opt_detection(boolopt[i].name, 0);
1992. 
1993. #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV)
1994. 			if (FALSE
1995. # ifdef TERMLIB
1996. 				 || (boolopt[i].addr) == &iflags.DECgraphics
1997. # endif
1998. # ifdef ASCIIGRAPH
1999. 				 || (boolopt[i].addr) == &iflags.IBMgraphics
2000. # endif
2001. # ifdef MAC_GRAPHICS_ENV
2002. 				 || (boolopt[i].addr) == &iflags.MACgraphics
2003. # endif
2004. 				) {
2005. # ifdef REINCARNATION
2006. 			    if (!initial && Is_rogue_level(&u.uz))
2007. 				assign_rogue_graphics(FALSE);
2008. # endif
2009. 			    need_redraw = TRUE;
2010. # ifdef TERMLIB
2011. 			    if ((boolopt[i].addr) == &iflags.DECgraphics)
2012. 				switch_graphics(iflags.DECgraphics ?
2013. 						DEC_GRAPHICS : ASCII_GRAPHICS);
2014. # endif
2015. # ifdef ASCIIGRAPH
2016. 			    if ((boolopt[i].addr) == &iflags.IBMgraphics)
2017. 				switch_graphics(iflags.IBMgraphics ?
2018. 						IBM_GRAPHICS : ASCII_GRAPHICS);
2019. # endif
2020. # ifdef MAC_GRAPHICS_ENV
2021. 			    if ((boolopt[i].addr) == &iflags.MACgraphics)
2022. 				switch_graphics(iflags.MACgraphics ?
2023. 						MAC_GRAPHICS : ASCII_GRAPHICS);
2024. # endif
2025. # ifdef REINCARNATION
2026. 			    if (!initial && Is_rogue_level(&u.uz))
2027. 				assign_rogue_graphics(TRUE);
2028. # endif
2029. 			}
2030. #endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */
2031. 
2032. 			/* only do processing below if setting with doset() */
2033. 			if (initial) return;
2034. 
2035. 			if ((boolopt[i].addr) == &flags.time
2036. #ifdef EXP_ON_BOTL
2037. 			 || (boolopt[i].addr) == &flags.showexp
2038. #endif
2039. #ifdef SCORE_ON_BOTL
2040. 			 || (boolopt[i].addr) == &flags.showscore
2041. #endif
2042. 			    )
2043. 			    flags.botl = TRUE;
2044. 
2045. 			else if ((boolopt[i].addr) == &flags.invlet_constant) {
2046. 			    if (flags.invlet_constant) reassign();
2047. 			}
2048. #ifdef LAN_MAIL
2049. 			else if ((boolopt[i].addr) == &flags.biff) {
2050. 			    if (flags.biff) lan_mail_init();
2051. 			    else lan_mail_finish();
2052. 			}
2053. #endif
2054. 			else if ((boolopt[i].addr) == &iflags.num_pad)
2055. 			    number_pad(iflags.num_pad ? 1 : 0);
2056. 
2057. 			else if ((boolopt[i].addr) == &flags.lit_corridor) {
2058. 			    /*
2059. 			     * All corridor squares seen via night vision or
2060. 			     * candles & lamps change.  Update them by calling
2061. 			     * newsym() on them.  Don't do this if we are
2062. 			     * initializing the options --- the vision system
2063. 			     * isn't set up yet.
2064. 			     */
2065. 			    vision_recalc(2);		/* shut down vision */
2066. 			    vision_full_recalc = 1;	/* delayed recalc */
2067. 			}
2068. 			else if ((boolopt[i].addr) == &iflags.use_inverse) {
2069. 			    need_redraw = TRUE;
2070. 			}
2071. 			else if ((boolopt[i].addr) == &iflags.hilite_pet) {
2072. 			    need_redraw = TRUE;
2073. 			}
2074. #ifdef TEXTCOLOR
2075. 			else if ((boolopt[i].addr) == &iflags.use_color) {
2076. 			    need_redraw = TRUE;
2077. # ifdef TOS
2078. 			    if ((boolopt[i].addr) == &iflags.use_color
2079. 				&& iflags.BIOS) {
2080. 				if (colors_changed)
2081. 				    restore_colors();
2082. 				else
2083. 				    set_colors();
2084. 			    }
2085. # endif
2086. 			}
2087. #endif
2088. 
2089. 			return;
2090. 		}
2091. 	}
2092. 
2093. 	/* out of valid options */
2094. 	badoption(opts);
2095. }
2096. 
2097. 
2098. static NEARDATA const char *menutype[] = {
2099. 	"traditional", "combination", "partial", "full"
2100. };
2101. 
2102. static NEARDATA const char *burdentype[] = {
2103. 	"unencumbered", "burdened", "stressed",
2104. 	"strained", "overtaxed", "overloaded"
2105. };
2106. 
2107. 
2108. /*
2109.  * Convert the given string of object classes to a string of default object
2110.  * symbols.
2111.  */
2112. STATIC_OVL void
2113. oc_to_str(src,dest)
2114.     char *src, *dest;
2115. {
2116.     int i;
2117. 
2118.     while ((i = (int) *src++) != 0) {
2119. 	if (i < 0 || i >= MAXOCLASSES)
2120. 	    impossible("oc_to_str:  illegal object class %d", i);
2121. 	else
2122. 	    *dest++ = def_oc_syms[i];
2123.     }
2124.     *dest = '\0';
2125. }
2126. 
2127. /*
2128.  * Add the given mapping to the menu command map list.  Always keep the
2129.  * maps valid C strings.
2130.  */
2131. void
2132. add_menu_cmd_alias(from_ch, to_ch)
2133.     char from_ch, to_ch;
2134. {
2135.     if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS)
2136. 	pline("out of menu map space");
2137.     else {
2138. 	mapped_menu_cmds[n_menu_mapped] = from_ch;
2139. 	mapped_menu_op[n_menu_mapped] = to_ch;
2140. 	n_menu_mapped++;
2141. 	mapped_menu_cmds[n_menu_mapped] = 0;
2142. 	mapped_menu_op[n_menu_mapped] = 0;
2143.     }
2144. }
2145. 
2146. /*
2147.  * Map the given character to its corresponding menu command.  If it
2148.  * doesn't match anything, just return the original.
2149.  */
2150. char
2151. map_menu_cmd(ch)
2152.     char ch;
2153. {
2154.     char *found = index(mapped_menu_cmds, ch);
2155.     if (found) {
2156. 	int idx = found - mapped_menu_cmds;
2157. 	ch = mapped_menu_op[idx];
2158.     }
2159.     return ch;
2160. }
2161. 
2162. 
2163. #if defined(MICRO) || defined(MAC)
2164. # define OPTIONS_HEADING "OPTIONS"
2165. #else
2166. # define OPTIONS_HEADING "NETHACKOPTIONS"
2167. #endif
2168. 
2169. static char fmtstr_doset_add_menu[] = "%s%-15s [%s]   "; 
2170. static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
2171. 
2172. STATIC_OVL void
2173. doset_add_menu(win, option, indexoffset)
2174.     winid win;			/* window to add to */
2175.     const char *option;		/* option name */
2176.     int indexoffset;		/* value to add to index in compopt[], or zero
2177. 				   if option cannot be changed */
2178. {
2179.     const char *value = "unknown";		/* current value */
2180.     char buf[BUFSZ], buf2[BUFSZ];
2181.     anything any;
2182.     int i;
2183. 
2184.     any.a_void = 0;
2185.     if (indexoffset == 0) {
2186. 	any.a_int = 0;
2187. 	value = get_compopt_value(option, buf2);
2188.     } else {
2189. 	for (i=0; compopt[i].name; i++)
2190. 	    if (strcmp(option, compopt[i].name) == 0) break;
2191. 
2192. 	if (compopt[i].name) {
2193. 	    any.a_int = i + 1 + indexoffset;
2194. 	    value = get_compopt_value(option, buf2);
2195. 	} else {
2196. 	    /* We are trying to add an option not found in compopt[].
2197. 	       This is almost certainly bad, but we'll let it through anyway
2198. 	       (with a zero value, so it can't be selected). */
2199. 	    any.a_int = 0;
2200. 	}
2201.     }
2202.     /* "    " replaces "a - " -- assumes menus follow that style */
2203.     if (!iflags.menu_tab_sep)
2204. 	Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ", option, value);
2205.     else
2206. 	Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
2207.     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
2208. }
2209. 
2210. /* Changing options via menu by Per Liboriussen */
2211. int
2212. doset()
2213. {
2214. 	char buf[BUFSZ], buf2[BUFSZ];
2215. 	int i, pass, boolcount, pick_cnt, pick_idx, opt_indx;
2216. 	boolean *bool_p;
2217. 	winid tmpwin;
2218. 	anything any;
2219. 	menu_item *pick_list;
2220. 	int indexoffset, startpass, endpass;
2221. 	boolean setinitial = FALSE, fromfile = FALSE;
2222. 	int biggest_name = 0;
2223. 
2224. 	tmpwin = create_nhwindow(NHW_MENU);
2225. 	start_menu(tmpwin);
2226. 
2227. 	any.a_void = 0;
2228. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2229. 		 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
2230. 	any.a_int = 0;
2231. 	/* first list any other non-modifiable booleans, then modifiable ones */
2232. 	for (pass = 0; pass <= 1; pass++)
2233. 	    for (i = 0; boolopt[i].name; i++)
2234. 		if ((bool_p = boolopt[i].addr) != 0 &&
2235. 			((boolopt[i].optflags == DISP_IN_GAME && pass == 0) ||
2236. 			 (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
2237. 		    if (bool_p == &flags.female) continue;  /* obsolete */
2238. #ifdef WIZARD
2239. 		    if (bool_p == &iflags.sanity_check && !wizard) continue;
2240. 		    if (bool_p == &iflags.menu_tab_sep && !wizard) continue;
2241. #endif
2242. 		    if (is_wc_option(boolopt[i].name) &&
2243. 			!wc_supported(boolopt[i].name)) continue;
2244. 		    any.a_int = (pass == 0) ? 0 : i + 1;
2245. 		    if (!iflags.menu_tab_sep)
2246. 			Sprintf(buf, "%s%-13s [%s]",
2247. 			    pass == 0 ? "    " : "",
2248. 			    boolopt[i].name, *bool_p ? "true" : "false");
2249.  		    else
2250. 			Sprintf(buf, "%s\t[%s]",
2251. 			    boolopt[i].name, *bool_p ? "true" : "false");
2252. 		    add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
2253. 			     ATR_NONE, buf, MENU_UNSELECTED);
2254. 		}
2255. 
2256. 	boolcount = i;
2257. 	indexoffset = boolcount;
2258. 	any.a_void = 0;
2259. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2260. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2261. 		 "Compounds (selecting will prompt for new value):",
2262. 		 MENU_UNSELECTED);
2263. 
2264. 	startpass = DISP_IN_GAME;
2265. 	endpass = SET_IN_GAME;
2266. 
2267. 	/* spin through the options to find the biggest name
2268.            and adjust the format string accordingly if needed */
2269. 	biggest_name = 0;
2270. 	for (i = 0; compopt[i].name; i++)
2271. 		if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass &&
2272. 		    strlen(compopt[i].name) > (unsigned) biggest_name)
2273. 			biggest_name = (int) strlen(compopt[i].name);
2274. 	if (biggest_name > 30) biggest_name = 30;
2275. 	if (!iflags.menu_tab_sep)
2276. 		Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
2277. 	
2278. 	/* deliberately put `name', `role', `race', `gender' first */
2279. 	doset_add_menu(tmpwin, "name", 0);
2280. 	doset_add_menu(tmpwin, "role", 0);
2281. 	doset_add_menu(tmpwin, "race", 0);
2282. 	doset_add_menu(tmpwin, "gender", 0);
2283. 
2284. 	for (pass = startpass; pass <= endpass; pass++) 
2285. 	    for (i = 0; compopt[i].name; i++)
2286. 		if (compopt[i].optflags == pass) {
2287.  		    	if (!strcmp(compopt[i].name, "name") ||
2288. 		    	    !strcmp(compopt[i].name, "role") ||
2289. 		    	    !strcmp(compopt[i].name, "race") ||
2290. 		    	    !strcmp(compopt[i].name, "gender"))
2291. 		    	    	continue;
2292. 		    	else if (is_wc_option(compopt[i].name) &&
2293. 					!wc_supported(compopt[i].name))
2294. 		    		continue;
2295. 		    	else
2296. 				doset_add_menu(tmpwin, compopt[i].name,
2297. 					(pass == DISP_IN_GAME) ? 0 : indexoffset);
2298. 		}
2299. #ifdef PREFIXES_IN_USE
2300. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2301. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2302. 		 "Variable playground locations:", MENU_UNSELECTED);
2303. 	for (i = 0; i < PREFIX_COUNT; i++)
2304. 		doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
2305. #endif
2306. 	end_menu(tmpwin, "Set what options?");
2307. 	need_redraw = FALSE;
2308. 	if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
2309. 	    /*
2310. 	     * Walk down the selection list and either invert the booleans
2311. 	     * or prompt for new values. In most cases, call parseoptions()
2312. 	     * to take care of options that require special attention, like
2313. 	     * redraws.
2314. 	     */
2315. 	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2316. 		opt_indx = pick_list[pick_idx].item.a_int - 1;
2317. 		if (opt_indx < boolcount) {
2318. 		    /* boolean option */
2319. 		    Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
2320. 			    boolopt[opt_indx].name);
2321. 		    parseoptions(buf, setinitial, fromfile);
2322. 		    if (wc_supported(boolopt[opt_indx].name))
2323. 			preference_update(boolopt[opt_indx].name);
2324. 		} else {
2325. 		    /* compound option */
2326. 		    opt_indx -= boolcount;
2327. 
2328. 		    if (!special_handling(compopt[opt_indx].name,
2329. 							setinitial, fromfile)) {
2330. 			Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
2331. 			getlin(buf, buf2);
2332. 			Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
2333. 			/* pass the buck */
2334. 			parseoptions(buf, setinitial, fromfile);
2335. 		    }
2336. 		    if (wc_supported(compopt[opt_indx].name))
2337. 			preference_update(compopt[opt_indx].name);
2338. 		}
2339. 	    }
2340. 	    free((genericptr_t)pick_list);
2341. 	    pick_list = (menu_item *)0;
2342. 	}
2343. 
2344. 	destroy_nhwindow(tmpwin);
2345. 	if (need_redraw)
2346. 	    (void) doredraw();
2347. 	return 0;
2348. }
2349. 
2350. STATIC_OVL boolean
2351. special_handling(optname, setinitial, setfromfile)
2352. const char *optname;
2353. boolean setinitial,setfromfile;
2354. {
2355.     winid tmpwin;
2356.     anything any;
2357.     int i;
2358.     char buf[BUFSZ];
2359.     boolean retval = FALSE;
2360.     
2361.     /* Special handling of menustyle, pickup_burden, and pickup_types, disclose options. */
2362.     if (!strcmp("menustyle", optname)) {
2363. 	const char *style_name;
2364. 	menu_item *style_pick = (menu_item *)0;
2365.         tmpwin = create_nhwindow(NHW_MENU);
2366. 	start_menu(tmpwin);
2367. 	for (i = 0; i < SIZE(menutype); i++) {
2368. 		style_name = menutype[i];
2369.     		/* note: separate `style_name' variable used
2370. 		   to avoid an optimizer bug in VAX C V2.3 */
2371. 		any.a_int = i + 1;
2372. 		add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0,
2373. 			 ATR_NONE, style_name, MENU_UNSELECTED);
2374.         }
2375. 	end_menu(tmpwin, "Select menustyle:");
2376. 	if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
2377. 		flags.menu_style = style_pick->item.a_int - 1;
2378. 		free((genericptr_t)style_pick);
2379.         }
2380. 	destroy_nhwindow(tmpwin);
2381.         retval = TRUE;
2382.     } else if (!strcmp("pickup_burden", optname)) {
2383. 	const char *burden_name, *burden_letters = "ubsntl";
2384. 	menu_item *burden_pick = (menu_item *)0;
2385.         tmpwin = create_nhwindow(NHW_MENU);
2386. 	start_menu(tmpwin);
2387. 	for (i = 0; i < SIZE(burdentype); i++) {
2388. 		burden_name = burdentype[i];
2389. 		any.a_int = i + 1;
2390. 		add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0,
2391. 			 ATR_NONE, burden_name, MENU_UNSELECTED);
2392.         }
2393. 	end_menu(tmpwin, "Select encumbrance level:");
2394. 	if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
2395. 		flags.pickup_burden = burden_pick->item.a_int - 1;
2396. 		free((genericptr_t)burden_pick);
2397. 	}
2398. 	destroy_nhwindow(tmpwin);
2399. 	retval = TRUE;
2400.     } else if (!strcmp("pickup_types", optname)) {
2401. 	/* parseoptions will prompt for the list of types */
2402. 	parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
2403. 	retval = TRUE;
2404.     } else if (!strcmp("disclose", optname)) {
2405. 	int pick_cnt, pick_idx, opt_idx;
2406. 	menu_item *disclosure_category_pick = (menu_item *)0;
2407. 	/*
2408. 	 * The order of disclose_names[]
2409.          * must correspond to disclosure_options in decl.h
2410.          */
2411. 	static const char *disclosure_names[] = {
2412. 		"inventory", "attributes", "vanquished", "genocides", "conduct"
2413. 	};
2414. 	int disc_cat[NUM_DISCLOSURE_OPTIONS];
2415. 	const char *disclosure_name;
2416. 
2417.         tmpwin = create_nhwindow(NHW_MENU);
2418. 	start_menu(tmpwin);
2419. 	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2420. 		disclosure_name = disclosure_names[i];
2421. 		any.a_int = i + 1;
2422. 		add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
2423. 			 ATR_NONE, disclosure_name, MENU_UNSELECTED);
2424. 		disc_cat[i] = 0;
2425.         }
2426. 	end_menu(tmpwin, "Change which disclosure options categories:");
2427. 	if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) {
2428. 	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2429. 		opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1;
2430. 		disc_cat[opt_idx] = 1;
2431. 	    }
2432. 	    free((genericptr_t)disclosure_category_pick);
2433. 	    disclosure_category_pick = (menu_item *)0;
2434. 	}
2435. 	destroy_nhwindow(tmpwin);
2436. 
2437. 	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2438. 	    if (disc_cat[i]) {
2439. 	    	char dbuf[BUFSZ];
2440. 		menu_item *disclosure_option_pick = (menu_item *)0;
2441. 		Sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]);
2442. 	        tmpwin = create_nhwindow(NHW_MENU);
2443. 		start_menu(tmpwin);
2444. 		any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
2445. 		add_menu(tmpwin, NO_GLYPH, &any, 'a', 0,
2446. 			ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED);
2447. 		any.a_void = 0;
2448. 		any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
2449. 		add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
2450. 			ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED);
2451. 		any.a_void = 0;
2452. 		any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
2453. 		add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
2454. 			ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED);
2455. 		any.a_void = 0;
2456. 		any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
2457. 		add_menu(tmpwin, NO_GLYPH, &any, 'd', 0,
2458. 			ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED);
2459. 		end_menu(tmpwin, dbuf);
2460. 		if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) {
2461. 			flags.end_disclose[i] = disclosure_option_pick->item.a_char;
2462. 			free((genericptr_t)disclosure_option_pick);
2463. 		}
2464. 		destroy_nhwindow(tmpwin);
2465. 	    }
2466. 	}
2467. 	retval = TRUE;
2468.     }
2469.     return retval;
2470. }
2471. 
2472. #define rolestring(val,array,field) ((val >= 0) ? array[val].field : \
2473. 				     (val == ROLE_RANDOM) ? randomrole : none)
2474. 
2475. /* This is ugly. We have all the option names in the compopt[] array,
2476.    but we need to look at each option individually to get the value. */
2477. STATIC_OVL const char *
2478. get_compopt_value(optname, buf)
2479. const char *optname;
2480. char *buf;
2481. {
2482. 	char ocl[MAXOCLASSES+1];
2483. 	static const char none[] = "(none)", randomrole[] = "random",
2484. 		     to_be_done[] = "(to be done)",
2485. 		     defopt[] = "default",
2486. 		     defbrief[] = "def";
2487. 	int i;
2488. 
2489. 	buf[0] = '\0';
2490. 	if (!strcmp(optname,"align_message"))
2491. 		Sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP     ? "top" :
2492. 				   iflags.wc_align_message == ALIGN_LEFT    ? "left" :
2493. 				   iflags.wc_align_message == ALIGN_BOTTOM  ? "bottom" :
2494. 				   iflags.wc_align_message == ALIGN_RIGHT   ? "right" :
2495. 				   defopt);
2496. 	else if (!strcmp(optname,"align_status"))
2497. 		Sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP     ? "top" :
2498. 				   iflags.wc_align_status == ALIGN_LEFT    ? "left" :
2499. 				   iflags.wc_align_status == ALIGN_BOTTOM  ? "bottom" :
2500. 				   iflags.wc_align_status == ALIGN_RIGHT   ? "right" :
2501. 				   defopt);
2502. 	else if (!strcmp(optname,"align"))
2503. 		Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
2504. 	else if (!strcmp(optname, "boulder"))
2505. 		Sprintf(buf, "%c", iflags.bouldersym ?
2506. 			iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]);
2507. 	else if (!strcmp(optname, "catname")) 
2508. 		Sprintf(buf, "%s", catname[0] ? catname : none );
2509. 	else if (!strcmp(optname, "disclose")) {
2510. 		for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2511. 			char topt[2];
2512. 			if (i) Strcat(buf," ");
2513. 			topt[1] = '\0';
2514. 			topt[0] = flags.end_disclose[i];
2515. 			Strcat(buf, topt);
2516. 			topt[0] = disclosure_options[i];
2517. 			Strcat(buf, topt);
2518. 		}
2519. 	}
2520. 	else if (!strcmp(optname, "dogname")) 
2521. 		Sprintf(buf, "%s", dogname[0] ? dogname : none );
2522. 	else if (!strcmp(optname, "dungeon"))
2523. 		Sprintf(buf, "%s", to_be_done);
2524. 	else if (!strcmp(optname, "effects"))
2525. 		Sprintf(buf, "%s", to_be_done);
2526. 	else if (!strcmp(optname, "font_map"))
2527. 		Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
2528. 	else if (!strcmp(optname, "font_message"))
2529. 		Sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt);
2530. 	else if (!strcmp(optname, "font_status"))
2531. 		Sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt);
2532. 	else if (!strcmp(optname, "font_menu"))
2533. 		Sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
2534. 	else if (!strcmp(optname, "font_text"))
2535. 		Sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt);
2536. 	else if (!strcmp(optname, "font_size_map")) {
2537. 		if (iflags.wc_fontsiz_map) Sprintf(buf, "%d", iflags.wc_fontsiz_map);
2538. 		else Strcpy(buf, defopt);
2539. 	}
2540. 	else if (!strcmp(optname, "font_size_message")) {
2541. 		if (iflags.wc_fontsiz_message) Sprintf(buf, "%d",
2542. 							iflags.wc_fontsiz_message);
2543. 		else Strcpy(buf, defopt);
2544. 	}
2545. 	else if (!strcmp(optname, "font_size_status")) {
2546. 		if (iflags.wc_fontsiz_status) Sprintf(buf, "%d", iflags.wc_fontsiz_status);
2547. 		else Strcpy(buf, defopt);
2548. 	}
2549. 	else if (!strcmp(optname, "font_size_menu")) {
2550. 		if (iflags.wc_fontsiz_menu) Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
2551. 		else Strcpy(buf, defopt);
2552. 	}
2553. 	else if (!strcmp(optname, "font_size_text")) {
2554. 		if (iflags.wc_fontsiz_text) Sprintf(buf, "%d",iflags.wc_fontsiz_text);
2555. 		else Strcpy(buf, defopt);
2556. 	}
2557. 	else if (!strcmp(optname, "fruit")) 
2558. 		Sprintf(buf, "%s", pl_fruit);
2559. 	else if (!strcmp(optname, "gender"))
2560. 		Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
2561. 	else if (!strcmp(optname, "horsename")) 
2562. 		Sprintf(buf, "%s", horsename[0] ? horsename : none);
2563. 	else if (!strcmp(optname, "map_mode"))
2564. 		Sprintf(buf, "%s",
2565. 			iflags.wc_map_mode == MAP_MODE_TILES      ? "tiles" :
2566. 			iflags.wc_map_mode == MAP_MODE_ASCII4x6   ? "ascii4x6" :
2567. 			iflags.wc_map_mode == MAP_MODE_ASCII6x8   ? "ascii6x8" :
2568. 			iflags.wc_map_mode == MAP_MODE_ASCII8x8   ? "ascii8x8" :
2569. 			iflags.wc_map_mode == MAP_MODE_ASCII16x8  ? "ascii16x8" :
2570. 			iflags.wc_map_mode == MAP_MODE_ASCII7x12  ? "ascii7x12" :
2571. 			iflags.wc_map_mode == MAP_MODE_ASCII8x12  ? "ascii8x12" :
2572. 			iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" :
2573. 			iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" :
2574. 			iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" :
2575. 			iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ?
2576. 			"fit_to_screen" : defopt);
2577. 	else if (!strcmp(optname, "menustyle")) 
2578. 		Sprintf(buf, "%s", menutype[(int)flags.menu_style] );
2579. 	else if (!strcmp(optname, "menu_deselect_all"))
2580. 		Sprintf(buf, "%s", to_be_done);
2581. 	else if (!strcmp(optname, "menu_deselect_page"))
2582. 		Sprintf(buf, "%s", to_be_done);
2583. 	else if (!strcmp(optname, "menu_first_page"))
2584. 		Sprintf(buf, "%s", to_be_done);
2585. 	else if (!strcmp(optname, "menu_invert_all"))
2586. 		Sprintf(buf, "%s", to_be_done);
2587. 	else if (!strcmp(optname, "menu_invert_page"))
2588. 		Sprintf(buf, "%s", to_be_done);
2589. 	else if (!strcmp(optname, "menu_last_page"))
2590. 		Sprintf(buf, "%s", to_be_done);
2591. 	else if (!strcmp(optname, "menu_next_page"))
2592. 		Sprintf(buf, "%s", to_be_done);
2593. 	else if (!strcmp(optname, "menu_previous_page"))
2594. 		Sprintf(buf, "%s", to_be_done);
2595. 	else if (!strcmp(optname, "menu_search"))
2596. 		Sprintf(buf, "%s", to_be_done);
2597. 	else if (!strcmp(optname, "menu_select_all"))
2598. 		Sprintf(buf, "%s", to_be_done);
2599. 	else if (!strcmp(optname, "menu_select_page"))
2600. 		Sprintf(buf, "%s", to_be_done);
2601. 	else if (!strcmp(optname, "monsters"))
2602. 		Sprintf(buf, "%s", to_be_done);
2603. 	else if (!strcmp(optname, "msghistory"))
2604. 		Sprintf(buf, "%u", iflags.msg_history);
2605. 	else if (!strcmp(optname, "name"))
2606. 		Sprintf(buf, "%s", plname);
2607. 	else if (!strcmp(optname, "objects"))
2608. 		Sprintf(buf, "%s", to_be_done);
2609. 	else if (!strcmp(optname, "packorder")) {
2610. 		oc_to_str(flags.inv_order, ocl);
2611. 		Sprintf(buf, "%s", ocl);
2612. 	     }
2613. #ifdef CHANGE_COLOR
2614. 	else if (!strcmp(optname, "palette")) 
2615. 		Sprintf(buf, "%s", get_color_string());
2616. #endif
2617. 	else if (!strcmp(optname, "pettype")) 
2618. 		Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" :
2619. 				(preferred_pet == 'd') ? "dog" :
2620. 				(preferred_pet == 'n') ? "none" : "random");
2621. 	else if (!strcmp(optname, "pickup_burden"))
2622. 		Sprintf(buf, "%s", burdentype[flags.pickup_burden] );
2623. 	else if (!strcmp(optname, "pickup_types")) {
2624. 		oc_to_str(flags.pickup_types, ocl);
2625. 		Sprintf(buf, "%s", ocl[0] ? ocl : "all" );
2626. 	     }
2627. 	else if (!strcmp(optname, "race"))
2628. 		Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
2629. 	else if (!strcmp(optname, "role"))
2630. 		Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
2631. 	else if (!strcmp(optname, "scores")) {
2632. 		Sprintf(buf, "%d top/%d around%s", flags.end_top,
2633. 				flags.end_around, flags.end_own ? "/own" : "");
2634. 	}
2635. 	else if (!strcmp(optname, "scroll_margin")) {
2636. 		if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin);
2637. 		else Strcpy(buf, defopt);
2638. 	}
2639. 	else if (!strcmp(optname, "player_selection"))
2640. 		Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
2641. #ifdef MSDOS
2642. 	else if (!strcmp(optname, "soundcard"))
2643. 		Sprintf(buf, "%s", to_be_done);
2644. #endif
2645. 	else if (!strcmp(optname, "suppress_alert")) {
2646. 	    if (flags.suppress_alert == 0L)
2647. 		Strcpy(buf, none);
2648. 	    else
2649. 		Sprintf(buf, "%lu.%lu.%lu",
2650. 			FEATURE_NOTICE_VER_MAJ,
2651. 			FEATURE_NOTICE_VER_MIN,
2652. 			FEATURE_NOTICE_VER_PATCH);
2653. 	}
2654. 	else if (!strcmp(optname, "tile_file"))
2655. 		Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
2656. 	else if (!strcmp(optname, "tile_height")) {
2657. 		if (iflags.wc_tile_height) Sprintf(buf, "%d",iflags.wc_tile_height);
2658. 		else Strcpy(buf, defopt);
2659. 	}
2660. 	else if (!strcmp(optname, "tile_width")) {
2661. 		if (iflags.wc_tile_width) Sprintf(buf, "%d",iflags.wc_tile_width);
2662. 		else Strcpy(buf, defopt);
2663. 	}
2664. 	else if (!strcmp(optname, "traps"))
2665. 		Sprintf(buf, "%s", to_be_done);
2666. 	else if (!strcmp(optname, "vary_msgcount")) {
2667. 		if (iflags.wc_vary_msgcount) Sprintf(buf, "%d",iflags.wc_vary_msgcount);
2668. 		else Strcpy(buf, defopt);
2669. 	}
2670. #ifdef MSDOS
2671. 	else if (!strcmp(optname, "video"))
2672. 		Sprintf(buf, "%s", to_be_done);
2673. #endif
2674. #ifdef VIDEOSHADES
2675. 	else if (!strcmp(optname, "videoshades"))
2676. 		Sprintf(buf, "%s-%s-%s", shade[0],shade[1],shade[2]);
2677. 	else if (!strcmp(optname, "videocolors"))
2678. 		Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
2679. 			ttycolors[CLR_RED], ttycolors[CLR_GREEN],
2680. 			ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
2681. 			ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
2682. 			ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
2683. 			ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
2684. 			ttycolors[CLR_BRIGHT_MAGENTA],
2685. 			ttycolors[CLR_BRIGHT_CYAN]);
2686. #endif /* VIDEOSHADES */
2687. 	else if (!strcmp(optname, "windowtype"))
2688. 		Sprintf(buf, "%s", windowprocs.name);
2689. 	else if (!strcmp(optname, "windowcolors"))
2690. 		Sprintf(buf, "%s/%s %s/%s %s/%s %s/%s",
2691. 			iflags.wc_foregrnd_menu    ? iflags.wc_foregrnd_menu : defbrief,
2692. 			iflags.wc_backgrnd_menu    ? iflags.wc_backgrnd_menu : defbrief,
2693. 			iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief,
2694. 			iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief,
2695. 			iflags.wc_foregrnd_status  ? iflags.wc_foregrnd_status : defbrief,
2696. 			iflags.wc_backgrnd_status  ? iflags.wc_backgrnd_status : defbrief,
2697. 			iflags.wc_foregrnd_text    ? iflags.wc_foregrnd_text : defbrief,
2698. 			iflags.wc_backgrnd_text    ? iflags.wc_backgrnd_text : defbrief);
2699. #ifdef PREFIXES_IN_USE
2700. 	else {
2701. 	    for (i = 0; i < PREFIX_COUNT; ++i)
2702. 		if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
2703. 			Sprintf(buf, "%s", fqn_prefix[i]);
2704. 	}
2705. #endif
2706. 
2707. 	if (buf[0]) return buf;
2708. 	else return "unknown";
2709. }
2710. 
2711. int
2712. dotogglepickup()
2713. {
2714. 	char buf[BUFSZ], ocl[MAXOCLASSES+1];
2715. 
2716. 	flags.pickup = !flags.pickup;
2717. 	if (flags.pickup) {
2718. 	    oc_to_str(flags.pickup_types, ocl);
2719. 	    Sprintf(buf, "ON, for %s objects", ocl[0] ? ocl : "all");
2720. 	} else {
2721. 	    Strcpy(buf, "OFF");
2722. 	}
2723. 	pline("Autopickup: %s.", buf);
2724. 	return 0;
2725. }
2726. 
2727. /* data for option_help() */
2728. static const char *opt_intro[] = {
2729. 	"",
2730. 	"                 NetHack Options Help:",
2731. 	"",
2732. #define CONFIG_SLOT 3	/* fill in next value at run-time */
2733. 	(char *)0,
2734. #if !defined(MICRO) && !defined(MAC)
2735. 	"or use `NETHACKOPTIONS=\"<options>\"' in your environment",
2736. #endif
2737. 	"(<options> is a list of options separated by commas)",
2738. #ifdef VMS
2739. 	"-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
2740. #endif
2741. 	"or press \"O\" while playing and use the menu.",
2742. 	"",
2743.  "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
2744. 	(char *)0
2745. };
2746. 
2747. static const char *opt_epilog[] = {
2748. 	"",
2749.  "Some of the options can be set only before the game is started; those",
2750. 	"items will not be selectable in the 'O' command's menu.",
2751. 	(char *)0
2752. };
2753. 
2754. void
2755. option_help()
2756. {
2757.     char buf[BUFSZ], buf2[BUFSZ];
2758.     register int i;
2759.     winid datawin;
2760. 
2761.     datawin = create_nhwindow(NHW_TEXT);
2762.     Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
2763.     opt_intro[CONFIG_SLOT] = (const char *) buf;
2764.     for (i = 0; opt_intro[i]; i++)
2765. 	putstr(datawin, 0, opt_intro[i]);
2766. 
2767.     /* Boolean options */
2768.     for (i = 0; boolopt[i].name; i++) {
2769. 	if (boolopt[i].addr) {
2770. #ifdef WIZARD
2771. 	    if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue;
2772. 	    if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue;
2773. #endif
2774. 	    next_opt(datawin, boolopt[i].name);
2775. 	}
2776.     }
2777.     next_opt(datawin, "");
2778. 
2779.     /* Compound options */
2780.     putstr(datawin, 0, "Compound options:");
2781.     for (i = 0; compopt[i].name; i++) {
2782. 	Sprintf(buf2, "`%s'", compopt[i].name);
2783. 	Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
2784. 		compopt[i+1].name ? ',' : '.');
2785. 	putstr(datawin, 0, buf);
2786.     }
2787. 
2788.     for (i = 0; opt_epilog[i]; i++)
2789. 	putstr(datawin, 0, opt_epilog[i]);
2790. 
2791.     display_nhwindow(datawin, FALSE);
2792.     destroy_nhwindow(datawin);
2793.     return;
2794. }
2795. 
2796. /*
2797.  * prints the next boolean option, on the same line if possible, on a new
2798.  * line if not. End with next_opt("").
2799.  */
2800. void
2801. next_opt(datawin, str)
2802. winid datawin;
2803. const char *str;
2804. {
2805. 	static char *buf = 0;
2806. 	int i;
2807. 	char *s;
2808. 
2809. 	if (!buf) *(buf = (char *)alloc(BUFSZ)) = '\0';
2810. 
2811. 	if (!*str) {
2812. 		s = eos(buf);
2813. 		if (s > &buf[1] && s[-2] == ',')
2814. 		    Strcpy(s - 2, ".");	/* replace last ", " */
2815. 		i = COLNO;	/* (greater than COLNO - 2) */
2816. 	} else {
2817. 		i = strlen(buf) + strlen(str) + 2;
2818. 	}
2819. 
2820. 	if (i > COLNO - 2) { /* rule of thumb */
2821. 		putstr(datawin, 0, buf);
2822. 		buf[0] = 0;
2823. 	}
2824. 	if (*str) {
2825. 		Strcat(buf, str);
2826. 		Strcat(buf, ", ");
2827. 	} else {
2828. 		putstr(datawin, 0, str);
2829. 		free(buf),  buf = 0;
2830. 	}
2831. 	return;
2832. }
2833. 
2834. /* Returns the fid of the fruit type; if that type already exists, it
2835.  * returns the fid of that one; if it does not exist, it adds a new fruit
2836.  * type to the chain and returns the new one.
2837.  */
2838. int
2839. fruitadd(str)
2840. char *str;
2841. {
2842. 	register int i;
2843. 	register struct fruit *f;
2844. 	struct fruit *lastf = 0;
2845. 	int highest_fruit_id = 0;
2846. 	char buf[PL_FSIZ];
2847. 	boolean user_specified = (str == pl_fruit);
2848. 	/* if not user-specified, then it's a fruit name for a fruit on
2849. 	 * a bones level...
2850. 	 */
2851. 
2852. 	/* Note: every fruit has an id (spe for fruit objects) of at least
2853. 	 * 1; 0 is an error.
2854. 	 */
2855. 	if (user_specified) {
2856. 		/* disallow naming after other foods (since it'd be impossible
2857. 		 * to tell the difference)
2858. 		 */
2859. 
2860. 		boolean found = FALSE, numeric = FALSE;
2861. 
2862. 		for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS;
2863. 						i++) {
2864. 			if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
2865. 				found = TRUE;
2866. 				break;
2867. 			}
2868. 		}
2869. 		{
2870. 		    char *c;
2871. 
2872. 		    c = pl_fruit;
2873. 
2874. 		    for(c = pl_fruit; *c >= '0' && *c <= '9'; c++)
2875. 			;
2876. 		    if (isspace(*c) || *c == 0) numeric = TRUE;
2877. 		}
2878. 		if (found || numeric ||
2879. 		    !strncmp(str, "cursed ", 7) ||
2880. 		    !strncmp(str, "uncursed ", 9) ||
2881. 		    !strncmp(str, "blessed ", 8) ||
2882. 		    !strncmp(str, "partly eaten ", 13) ||
2883. 		    (!strncmp(str, "tin of ", 7) &&
2884. 			(!strcmp(str+7, "spinach") ||
2885. 			 name_to_mon(str+7) >= LOW_PM)) ||
2886. 		    !strcmp(str, "empty tin") ||
2887. 		    ((!strncmp(eos(str)-7," corpse",7) ||
2888. 			    !strncmp(eos(str)-4, " egg",4)) &&
2889. 			name_to_mon(str) >= LOW_PM))
2890. 			{
2891. 				Strcpy(buf, pl_fruit);
2892. 				Strcpy(pl_fruit, "candied ");
2893. 				nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
2894. 		}
2895. 	}
2896. 	for(f=ffruit; f; f = f->nextf) {
2897. 		lastf = f;
2898. 		if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
2899. 		if(!strncmp(str, f->fname, PL_FSIZ))
2900. 			goto nonew;
2901. 	}
2902. 	/* if adding another fruit would overflow spe, use a random
2903. 	   fruit instead... we've got a lot to choose from. */
2904. 	if (highest_fruit_id >= 127) return rnd(127);
2905. 	highest_fruit_id++;
2906. 	f = newfruit();
2907. 	if (ffruit) lastf->nextf = f;
2908. 	else ffruit = f;
2909. 	Strcpy(f->fname, str);
2910. 	f->fid = highest_fruit_id;
2911. 	f->nextf = 0;
2912. nonew:
2913. 	if (user_specified) current_fruit = highest_fruit_id;
2914. 	return f->fid;
2915. }
2916. 
2917. /*
2918.  * This is a somewhat generic menu for taking a list of NetHack style
2919.  * class choices and presenting them via a description
2920.  * rather than the traditional NetHack characters.
2921.  * (Benefits users whose first exposure to NetHack is via tiles).
2922.  *
2923.  * prompt
2924.  *	     The title at the top of the menu.
2925.  *
2926.  * category: 0 = monster class
2927.  *           1 = object  class
2928.  *
2929.  * way
2930.  *	     FALSE = PICK_ONE, TRUE = PICK_ANY
2931.  *
2932.  * class_list
2933.  *	     a null terminated string containing the list of choices.
2934.  *
2935.  * class_selection
2936.  *	     a null terminated string containing the selected characters.
2937.  *
2938.  * Returns number selected.
2939.  */
2940. int
2941. choose_classes_menu(prompt, category, way, class_list, class_select)
2942. const char *prompt;
2943. int category;
2944. boolean way;
2945. char *class_list;
2946. char *class_select;
2947. {
2948.     menu_item *pick_list = (menu_item *)0;
2949.     winid win;
2950.     anything any;
2951.     char buf[BUFSZ];
2952.     int i, n;
2953.     int ret;
2954.     int next_accelerator, accelerator;
2955. 
2956.     if (class_list == (char *)0 || class_select == (char *)0) return 0;
2957.     accelerator = 0;
2958.     next_accelerator = 'a';
2959.     any.a_void = 0;
2960.     win = create_nhwindow(NHW_MENU);
2961.     start_menu(win);
2962.     while (*class_list) {
2963. 	const char *text;
2964. 	boolean selected;
2965. 
2966. 	text = (char *)0;
2967. 	selected = FALSE;
2968. 	switch (category) {
2969. 		case 0:
2970. 			text = monexplain[def_char_to_monclass(*class_list)];
2971. 			accelerator = *class_list;
2972. 			Sprintf(buf, "%s", text);
2973. 			break;
2974. 		case 1:
2975. 			text = objexplain[def_char_to_objclass(*class_list)];
2976. 			accelerator = next_accelerator;
2977. 			Sprintf(buf, "%c  %s", *class_list, text);
2978. 			break;
2979. 		default:
2980. 			impossible("choose_classes_menu: invalid category %d",
2981. 					category);
2982. 	}
2983. 	if (way && *class_select) {	/* Selections there already */
2984. 		if (index(class_select, *class_list)) {
2985. 			selected = TRUE;
2986. 		}
2987. 	}
2988. 	any.a_int = *class_list;
2989. 	add_menu(win, NO_GLYPH, &any, accelerator,
2990. 		  category ? *class_list : 0,
2991. 		  ATR_NONE, buf, selected);
2992. 	++class_list;
2993. 	if (category > 0) {
2994. 		++next_accelerator;
2995. 		if (next_accelerator == ('z' + 1)) next_accelerator = 'A';
2996. 		if (next_accelerator == ('Z' + 1)) break;
2997. 	}
2998.     }
2999.     end_menu(win, prompt);
3000.     n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
3001.     destroy_nhwindow(win);
3002.     if (n > 0) {
3003. 	for (i = 0; i < n; ++i)
3004. 	    *class_select++ = (char)pick_list[i].item.a_int;
3005. 	free((genericptr_t)pick_list);
3006. 	ret = n;
3007.     } else if (n == -1) {
3008. 	class_select = eos(class_select);
3009. 	ret = -1;
3010.     } else
3011. 	ret = 0;
3012.     *class_select = '\0';
3013.     return ret;
3014. }
3015. 
3016. struct wc_Opt wc_options[] = {
3017. 	{"ascii_map", WC_ASCII_MAP},
3018. 	{"color", WC_COLOR},
3019. 	{"eight_bit_tty", WC_EIGHT_BIT_IN},
3020. 	{"hilite_pet", WC_HILITE_PET},
3021. 	{"large_font", WC_LARGE_FONT},	/* now obsolete */
3022. 	{"popup_dialog", WC_POPUP_DIALOG},
3023. 	{"preload_tiles", WC_PRELOAD_TILES},
3024. 	{"tiled_map", WC_TILED_MAP},
3025. 	{"tile_file", WC_TILE_FILE},
3026. 	{"tile_width", WC_TILE_WIDTH},
3027. 	{"tile_height", WC_TILE_HEIGHT},
3028. 	{"use_inverse", WC_INVERSE},
3029. 	{"align_message", WC_ALIGN_MESSAGE},
3030. 	{"align_status", WC_ALIGN_STATUS},
3031. 	{"font_map", WC_FONT_MAP},
3032. 	{"font_menu", WC_FONT_MENU},
3033. 	{"font_message",WC_FONT_MESSAGE},
3034. #if 0
3035. 	{"perm_invent",WC_PERM_INVENT},
3036. #endif
3037. 	{"font_size_map", WC_FONTSIZ_MAP},
3038. 	{"font_size_menu", WC_FONTSIZ_MENU},
3039. 	{"font_size_message", WC_FONTSIZ_MESSAGE},
3040. 	{"font_size_status", WC_FONTSIZ_STATUS},
3041. 	{"font_size_text", WC_FONTSIZ_TEXT},
3042. 	{"font_status", WC_FONT_STATUS},
3043. 	{"font_text", WC_FONT_TEXT},
3044. 	{"map_mode", WC_MAP_MODE},
3045. 	{"scroll_margin", WC_SCROLL_MARGIN},
3046. 	{"vary_msgcount",WC_VARY_MSGCOUNT},
3047. 	{(char *)0, 0L}
3048. };
3049. 
3050. 
3051. /*
3052.  * If a port wants to change or ensure that the
3053.  * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
3054.  * correct (for controlling its display in the option menu) call
3055.  * set_option_mod_status()
3056.  * with the second argument of 0,2, or 3 respectively.
3057.  */
3058. void
3059. set_option_mod_status(optnam, status)
3060. char *optnam;
3061. int status;
3062. {
3063. 	int k;
3064. 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
3065. 		impossible("set_option_mod_status: status out of range %d.", status);
3066. 		return;
3067. 	}
3068. 	for (k = 0; boolopt[k].name; k++) {
3069. 		if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
3070. 			boolopt[k].optflags = status;
3071. 			return;
3072. 		}
3073. 	}
3074. 	for (k = 0; compopt[k].name; k++) {
3075. 		if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
3076. 			compopt[k].optflags = status;
3077. 			return;
3078. 		}
3079. 	}
3080. }
3081. 
3082. /*
3083.  * You can set several wc_options in one call to
3084.  * set_wc_option_mod_status() by setting
3085.  * the appropriate bits for each option that you
3086.  * are setting in the optmask argument
3087.  * prior to calling.
3088.  *    example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME);
3089.  */
3090. void
3091. set_wc_option_mod_status(optmask, status)
3092. unsigned long optmask;
3093. int status;
3094. {
3095. 	int k = 0;
3096. 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
3097. 		impossible("set_option_mod_status: status out of range %d.", status);
3098. 		return;
3099. 	}
3100. 	while (wc_options[k].wc_name) {
3101. 		if (optmask & wc_options[k].wc_bit) {
3102. 			set_option_mod_status(wc_options[k].wc_name, status);
3103. 		}
3104. 		k++;
3105. 	}
3106. }
3107. 
3108. STATIC_OVL boolean
3109. is_wc_option(optnam)
3110. const char *optnam;
3111. {
3112. 	int k = 0;
3113. 	while (wc_options[k].wc_name) {
3114. 		if (strcmp(wc_options[k].wc_name, optnam) == 0)
3115. 			return TRUE;
3116. 		k++;
3117. 	}
3118. 	return FALSE;
3119. }
3120. 
3121. STATIC_OVL boolean
3122. wc_supported(optnam)
3123. const char *optnam;
3124. {
3125. 	int k = 0;
3126. 	while (wc_options[k].wc_name) {
3127. 		if (!strcmp(wc_options[k].wc_name, optnam) &&
3128. 		    (windowprocs.wincap & wc_options[k].wc_bit))
3129. 			return TRUE;
3130. 		k++;
3131. 	}
3132. 	return FALSE;
3133. }
3134. 
3135. STATIC_OVL void
3136. wc_set_font_name(wtype, fontname)
3137. int wtype;
3138. char *fontname;
3139. {
3140. 	char **fn = (char **)0;
3141. 	if (!fontname) return;
3142. 	switch(wtype) {
3143. 	    case NHW_MAP:
3144. 	    		fn = &iflags.wc_font_map;
3145. 			break;
3146. 	    case NHW_MESSAGE:
3147. 	    		fn = &iflags.wc_font_message;
3148. 			break;
3149. 	    case NHW_TEXT:
3150. 	    		fn = &iflags.wc_font_text;
3151. 			break;
3152. 	    case NHW_MENU:
3153. 	    		fn = &iflags.wc_font_menu;
3154. 			break;
3155. 	    case NHW_STATUS:
3156. 	    		fn = &iflags.wc_font_status;
3157. 			break;
3158. 	    default:
3159. 	    		return;
3160. 	}
3161. 	if (fn) {
3162. 		if (*fn) free(*fn);
3163. 		*fn = (char *)alloc(strlen(fontname) + 1);
3164. 		Strcpy(*fn, fontname);
3165. 	}
3166. 	return;
3167. }
3168. 
3169. STATIC_OVL int
3170. wc_set_window_colors(op)
3171. char *op;
3172. {
3173. 	/* syntax:
3174. 	 *  menu white/black message green/yellow status white/blue text white/black
3175. 	 */
3176. 
3177. 	int j;
3178. 	char buf[BUFSZ];
3179. 	char *wn, *tfg, *tbg, *newop;
3180. 	static char *wnames[] = {"menu", "message", "status", "text"};
3181. 	static char *shortnames[] = {"mnu", "msg", "sts", "txt"};
3182. 	static char **fgp[] = {
3183. 		&iflags.wc_foregrnd_menu,
3184. 		&iflags.wc_foregrnd_message,
3185. 		&iflags.wc_foregrnd_status,
3186. 		&iflags.wc_foregrnd_text
3187. 	};
3188. 	static char **bgp[] = {
3189. 		&iflags.wc_backgrnd_menu,
3190. 		&iflags.wc_backgrnd_message,
3191. 		&iflags.wc_backgrnd_status,
3192. 		&iflags.wc_backgrnd_text
3193. 	};
3194. 
3195. 	Strcpy(buf, op);
3196. 	newop = mungspaces(buf);
3197. 	while (newop && *newop) {
3198. 
3199. 		wn = tfg = tbg = (char *)0;
3200. 
3201. 		/* until first non-space in case there's leading spaces - before colorname*/
3202. 		while(*newop && isspace(*newop)) newop++;
3203. 		if (*newop) wn = newop;
3204. 		else return 0;
3205. 
3206. 		/* until first space - colorname*/
3207. 		while(*newop && !isspace(*newop)) newop++;
3208. 		if (*newop) *newop = '\0';
3209. 		else return 0;
3210. 		newop++;
3211. 
3212. 		/* until first non-space - before foreground*/
3213. 		while(*newop && isspace(*newop)) newop++;
3214. 		if (*newop) tfg = newop;
3215. 		else return 0;
3216. 
3217. 		/* until slash - foreground */
3218. 		while(*newop && *newop != '/') newop++;
3219. 		if (*newop) *newop = '\0';
3220. 		else return 0;
3221. 		newop++;
3222. 
3223. 		/* until first non-space (in case there's leading space after slash) - before background */
3224. 		while(*newop && isspace(*newop)) newop++;
3225. 		if (*newop) tbg = newop;
3226. 		else return 0;
3227. 
3228. 		/* until first space - background */
3229. 		while(*newop && !isspace(*newop)) newop++;
3230. 		if (*newop) *newop++ = '\0';
3231. 
3232. 		for (j = 0; j < 4; ++j) {
3233. 			if (!strcmpi(wn, wnames[j]) ||
3234. 			    !strcmpi(wn, shortnames[j])) {
3235. 				if (tfg && !strstri(tfg, " ")) {
3236. 					if (*fgp[j]) free(*fgp[j]);
3237. 					*fgp[j] = (char *)alloc(strlen(tfg) + 1);
3238. 					Strcpy(*fgp[j], tfg);
3239. 				}
3240. 				if (tbg && !strstri(tbg, " ")) {
3241. 					if (*bgp[j]) free(*bgp[j]);
3242. 					*bgp[j] = (char *)alloc(strlen(tbg) + 1);
3243. 					Strcpy(*bgp[j], tbg);
3244. 				}
3245.  				break;
3246. 			}
3247. 		}
3248. 	}
3249. 	return 1;
3250. }
3251. 
3252. #endif	/* OPTION_LISTS_ONLY */
3253. 
3254. /*options.c*/