Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/options.c

2,035pages on
this wiki
Add New Page
Talk0

Below is the full text to options.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/options.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)options.c	3.4	2003/11/14	*/
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.   #if defined(GL_GRAPHICS) || defined(SDL_GRAPHICS)
19.   #include "winGL.h"  /* Sdlgl_parse_options */
20.   #endif
21.   
22.   #include "filename.h"
23.   
24.   #define WINTYPELEN 16
25.   
26.   #ifdef DEFAULT_WC_TILED_MAP
27.   #define PREFER_TILED TRUE
28.   #else
29.   #define PREFER_TILED FALSE
30.   #endif
31.   
32.   /*
33.    *  NOTE:  If you add (or delete) an option, please update the short
34.    *  options help (option_help()), the long options help (dat/opthelp),
35.    *  and the current options setting display function (doset()),
36.    *  and also the Guidebooks.
37.    *
38.    *  The order matters.  If an option is a an initial substring of another
39.    *  option (e.g. time and timed_delay) the shorter one must come first.
40.    */
41.   
42.   static struct Bool_Opt
43.   {
44.   	const char *name;
45.   	boolean	*addr, initvalue;
46.   	int optflags;
47.   } boolopt[] = {
48.   #ifdef AMIGA
49.   	{"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME},
50.   #else
51.   	{"altmeta", (boolean *)0, TRUE, DISP_IN_GAME},
52.   #endif
53.   	{"ascii_map",     &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME},	/*WC*/
54.   #ifdef MFLOPPY
55.   	{"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME},
56.   #else
57.   	{"asksavedisk", (boolean *)0, FALSE, SET_IN_GAME},
58.   #endif
59.   	{"autodig", &flags.autodig, FALSE, SET_IN_GAME},
60.   	{"autopickup", &flags.pickup, TRUE, SET_IN_GAME},
61.   	{"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME},
62.   #if defined(MICRO) && !defined(AMIGA)
63.   	{"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE},
64.   #else
65.   	{"BIOS", (boolean *)0, FALSE, SET_IN_FILE},
66.   #endif
67.   #ifdef INSURANCE
68.   	{"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME},
69.   #else
70.   	{"checkpoint", (boolean *)0, FALSE, SET_IN_FILE},
71.   #endif
72.   #ifdef MFLOPPY
73.   	{"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME},
74.   #else
75.   	{"checkspace", (boolean *)0, FALSE, SET_IN_FILE},
76.   #endif
77.   	{"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME},
78.   # if defined(MICRO) || defined(WIN32)
79.   	{"color",         &iflags.wc_color,TRUE, SET_IN_GAME},		/*WC*/
80.   # else	/* systems that support multiple terminals, many monochrome */
81.   	{"color",         &iflags.wc_color, FALSE, SET_IN_GAME},	/*WC*/
82.   # endif
83.   	{"confirm",&flags.confirm, TRUE, SET_IN_GAME},
84.   #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
85.   	{"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
86.   #else
87.   	{"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE},
88.   #endif
89.   	{"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME},	/*WC*/
90.   #ifdef TTY_GRAPHICS
91.   	{"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME},
92.   #else
93.   	{"extmenu", (boolean *)0, FALSE, SET_IN_FILE},
94.   #endif
95.   #ifdef OPT_DISPMAP
96.   	{"fast_map", &flags.fast_map, TRUE, SET_IN_GAME},
97.   #else
98.   	{"fast_map", (boolean *)0, TRUE, SET_IN_FILE},
99.   #endif
100.  	{"female", &flags.female, FALSE, DISP_IN_GAME},
101.  	{"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME},
102.  #ifdef AMIFLUSH
103.  	{"flush", &flags.amiflush, FALSE, SET_IN_GAME},
104.  #else
105.  	{"flush", (boolean *)0, FALSE, SET_IN_FILE},
106.  #endif
107.  	{"fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE},
108.  	{"help", &flags.help, TRUE, SET_IN_GAME},
109.  	{"hilite_pet",    &iflags.wc_hilite_pet, FALSE, SET_IN_GAME},	/*WC*/
110.  #ifdef ASCIIGRAPH
111.  	{"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME},
112.  #else
113.  	{"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE},
114.  #endif
115.  #ifndef MAC
116.  	{"ignintr", &flags.ignintr, FALSE, SET_IN_GAME},
117.  #else
118.  	{"ignintr", (boolean *)0, FALSE, SET_IN_FILE},
119.  #endif
120.  #ifdef SHOW_WEIGHT
121.  	{"invweight", &flags.invweight, FALSE, SET_IN_GAME},
122.  #else
123.  	{"invweight", (boolean *)0, FALSE, SET_IN_FILE},
124.  #endif
125.  /*WAC the keep savefile option...*/
126.  #ifdef KEEP_SAVE
127.  	{"keep_savefile", &flags.keep_savefile, FALSE, SET_IN_FILE},
128.  #else
129.  	{"keep_savefile", (boolean *)0, FALSE, DISP_IN_GAME},
130.  #endif
131.  	{"large_font", &iflags.obsolete, FALSE, SET_IN_FILE},	/* OBSOLETE */
132.  	{"legacy", &flags.legacy, TRUE, DISP_IN_GAME},
133.  	{"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME},
134.  	{"lootabc", &iflags.lootabc, FALSE, SET_IN_GAME},
135.  #ifdef MAC_GRAPHICS_ENV
136.  	{"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME},
137.  #else
138.  	{"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE},
139.  #endif
140.  #ifdef MAIL
141.  	{"mail", &flags.biff, TRUE, SET_IN_GAME},
142.  #else
143.  	{"mail", (boolean *)0, TRUE, SET_IN_FILE},
144.  #endif
145.  #ifdef MENU_COLOR
146.  # ifdef MICRO
147.  	{"menucolors", &iflags.use_menu_color, TRUE,  SET_IN_GAME},
148.  # else
149.  	{"menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME},
150.  # endif
151.  #else
152.  	{"menucolors", (boolean *)0, FALSE, SET_IN_GAME},
153.  #endif
154.  	{"menu_on_esc", &flags.menu_on_esc, TRUE, SET_IN_GAME},
155.  #ifdef WIZARD
156.  	/* for menu debugging only*/
157.  	{"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME},
158.  #else
159.  	{"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE},
160.  #endif
161.  #ifdef WIZARD
162.  	{"mon_polycontrol", &iflags.mon_polycontrol, FALSE, SET_IN_GAME},
163.  #else
164.  	{"mon_polycontrol", (boolean *)0, FALSE, SET_IN_FILE},
165.  #endif
166.  	{"mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME},	/*WC*/
167.  #ifdef NEWS
168.  	{"news", &iflags.news, TRUE, DISP_IN_GAME},
169.  #else
170.  	{"news", (boolean *)0, FALSE, SET_IN_FILE},
171.  #endif
172.  	{"null", &flags.null, TRUE, SET_IN_GAME},
173.  #ifdef MAC
174.  	{"page_wait", &flags.page_wait, TRUE, SET_IN_GAME},
175.  #else
176.  	{"page_wait", (boolean *)0, FALSE, SET_IN_FILE},
177.  #endif
178.  	{"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME},
179.  	{"pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME},
180.  	{"popup_dialog",  &iflags.wc_popup_dialog, FALSE, SET_IN_GAME},	/*WC*/
181.  	{"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME},
182.  	{"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME},	/*WC*/
183.  	{"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME},
184.  	{"radar", (boolean *)0, FALSE, SET_IN_FILE},	/* OBSOLETE */
185.  #if defined(MICRO) && !defined(AMIGA)
186.  	{"rawio", &iflags.rawio, FALSE, DISP_IN_GAME},
187.  #else
188.  	{"rawio", (boolean *)0, FALSE, SET_IN_FILE},
189.  #endif
190.  	{"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME},
191.  	{"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
192.  #if defined(OBJ_SANITY)
193.  	{"sanity_check", &iflags.sanity_check, TRUE, SET_IN_GAME},
194.  #elif defined(WIZARD)
195.  	{"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
196.  #else
197.  	{"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
198.  #endif
199.  #ifdef EXP_ON_BOTL
200.  	{"showexp", &flags.showexp, FALSE, SET_IN_GAME},
201.  #else
202.  	{"showexp", (boolean *)0, FALSE, SET_IN_FILE},
203.  #endif
204.  	{"showrace", &iflags.showrace, FALSE, SET_IN_GAME},
205.  #ifdef SCORE_ON_BOTL
206.  	{"showscore", &flags.showscore, FALSE, SET_IN_GAME},
207.  #else
208.  	{"showscore", (boolean *)0, FALSE, SET_IN_FILE},
209.  #endif
210.  /* WAC made the [ xx pts]  dmg display optional */
211.  #ifdef SHOW_DMG
212.  	{"showdmg", &flags.showdmg, FALSE, SET_IN_GAME},
213.  #else
214.  	{"showdmg", (boolean *)0, FALSE, SET_IN_FILE},
215.  #endif
216.  #ifdef SHOW_WEIGHT
217.  	{"showweight", &flags.showweight, FALSE, SET_IN_GAME},
218.  #else
219.  	{"showweight", (boolean *)0, FALSE, SET_IN_FILE},
220.  #endif
221.  	{"silent", &flags.silent, TRUE, SET_IN_GAME},
222.  	{"softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE},
223.  	{"sortpack", &flags.sortpack, TRUE, SET_IN_GAME},
224.  	{"sound", &flags.soundok, TRUE, SET_IN_GAME},
225.  	{"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
226.  	{"standout", &flags.standout, FALSE, SET_IN_GAME},
227.  	{"splash_screen",     &iflags.wc_splash_screen, TRUE, DISP_IN_GAME},	/*WC*/
228.  	{"tiled_map",     &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME},	/*WC*/
229.  	{"time", &flags.time, FALSE, SET_IN_GAME},
230.  #ifdef TIMED_DELAY
231.  	{"timed_delay", &flags.nap, TRUE, SET_IN_GAME},
232.  #else
233.  	{"timed_delay", (boolean *)0, FALSE, SET_IN_GAME},
234.  #endif
235.  	{"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
236.  	{"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
237.  	{"travel", &iflags.travelcmd, TRUE, SET_IN_GAME},
238.  #ifdef WIN32CON
239.  	{"use_inverse",   &iflags.wc_inverse, TRUE, SET_IN_GAME},		/*WC*/
240.  #else
241.  	{"use_inverse",   &iflags.wc_inverse, FALSE, SET_IN_GAME},		/*WC*/
242.  #endif
243.  	{"verbose", &flags.verbose, TRUE, SET_IN_GAME},
244.  	{"wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME},
245.  	{(char *)0, (boolean *)0, FALSE, 0}
246.  };
247.  
248.  genericptr_t nh_option_get_boolopt()
249.  {
250.      return (genericptr_t)boolopt;
251.  }
252.  
253.  /* compound options, for option_help() and external programs like Amiga
254.   * frontend */
255.  static struct Comp_Opt
256.  {
257.  	const char *name, *descr;
258.  	int size;	/* for frontends and such allocating space --
259.  			 * usually allowed size of data in game, but
260.  			 * occasionally maximum reasonable size for
261.  			 * typing when game maintains information in
262.  			 * a different format */
263.  	int optflags;
264.  } compopt[] = {
265.  	{ "align",    "your starting alignment (lawful, neutral, or chaotic)",
266.  						8, DISP_IN_GAME },
267.  	{ "align_message", "message window alignment", 20, DISP_IN_GAME }, 	/*WC*/
268.  	{ "align_status", "status window alignment", 20, DISP_IN_GAME }, 	/*WC*/
269.  	{ "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
270.  	{ "boulder",  "the symbol to use for displaying boulders",
271.  						1, SET_IN_GAME },
272.  	{ "catname",  "the name of your (first) cat (e.g., catname:Tabby)",
273.  						PL_PSIZ, DISP_IN_GAME },
274.  	{ "disclose", "the kinds of information to disclose at end of game",
275.  						sizeof(flags.end_disclose) * 2,
276.  						SET_IN_GAME },
277.  	{ "dogname",  "the name of your (first) dog (e.g., dogname:Fang)",
278.  						PL_PSIZ, DISP_IN_GAME },
279.  	{ "dungeon",  "the symbols to use in drawing the dungeon map",
280.  						MAXDCHARS+1, SET_IN_FILE },
281.  	{ "effects",  "the symbols to use in drawing special effects",
282.  						MAXECHARS+1, SET_IN_FILE },
283.  	{ "font_map", "the font to use in the map window", 40, DISP_IN_GAME },	/*WC*/
284.  	{ "font_menu", "the font to use in menus", 40, DISP_IN_GAME },		/*WC*/
285.  	{ "font_message", "the font to use in the message window",
286.  						40, DISP_IN_GAME },		/*WC*/
287.  	{ "font_size_map", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
288.  	{ "font_size_menu", "the size of the menu font", 20, DISP_IN_GAME },	/*WC*/
289.  	{ "font_size_message", "the size of the message font", 20, DISP_IN_GAME },	/*WC*/
290.  	{ "font_size_status", "the size of the status font", 20, DISP_IN_GAME },	/*WC*/
291.  	{ "font_size_text", "the size of the text font", 20, DISP_IN_GAME },	/*WC*/
292.  	{ "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/
293.  	{ "font_text", "the font to use in text windows", 40, DISP_IN_GAME },	/*WC*/
294.  	{ "fruit",    "the name of a fruit you enjoy eating",
295.  						PL_FSIZ, SET_IN_GAME },
296.  	{ "gender",   "your starting gender (male or female)",
297.  						8, DISP_IN_GAME },
298.  	{ "ghoulname",  "the name of your (first) ghoul (e.g., ghoulname:Casper)",
299.  						PL_PSIZ, DISP_IN_GAME },
300.  	{ "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
301.  						PL_PSIZ, DISP_IN_GAME },
302.  	{ "map_mode", "map display mode under Windows", 20, DISP_IN_GAME },	/*WC*/
303.          { "menucolor", "set menu colors", PL_PSIZ, SET_IN_FILE },
304.  	{ "menustyle", "user interface for object selection",
305.  						MENUTYPELEN, SET_IN_GAME },
306.  	{ "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
307.  	{ "menu_deselect_page", "deselect all items on this page of a menu",
308.  						4, SET_IN_FILE },
309.  	{ "menu_first_page", "jump to the first page in a menu",
310.  						4, SET_IN_FILE },
311.  	{ "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME },
312.  	{ "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
313.  	{ "menu_invert_page", "invert all items on this page of a menu",
314.  						4, SET_IN_FILE },
315.  	{ "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
316.  	{ "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
317.  	{ "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
318.  	{ "menu_search", "search for a menu item", 4, SET_IN_FILE },
319.  	{ "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
320.  	{ "menu_select_page", "select all items on this page of a menu",
321.  						4, SET_IN_FILE },
322.  	{ "monsters", "the symbols to use for monsters",
323.  						MAXMCLASSES, SET_IN_FILE },
324.  	{ "msghistory", "number of top line messages to save",
325.  						5, DISP_IN_GAME },
326.  # ifdef TTY_GRAPHICS
327.  	{"msg_window", "the type of message window required",1, SET_IN_GAME},
328.  # else
329.  	{"msg_window", "the type of message window required", 1, SET_IN_FILE},
330.  # endif
331.  	{ "name",     "your character's name (e.g., name:Merlin-W)",
332.  						PL_NSIZ, DISP_IN_GAME },
333.  	{ "number_pad", "use the number pad", 1, SET_IN_GAME},
334.  	{ "objects",  "the symbols to use for objects",
335.  						MAXOCLASSES, SET_IN_FILE },
336.  	{ "packorder", "the inventory order of the items in your pack",
337.  						MAXOCLASSES, SET_IN_GAME },
338.  #ifdef CHANGE_COLOR
339.  	{ "palette",  "palette (00c/880/-fff is blue/yellow/reverse white)",
340.  						15 , SET_IN_GAME },
341.  # if defined(MAC)
342.  	{ "hicolor",  "same as palette, only order is reversed",
343.  						15, SET_IN_FILE },
344.  # endif
345.  #endif
346.  	{ "pettype",  "your preferred initial pet type", 4, DISP_IN_GAME },
347.  	{ "pickup_burden",  "maximum burden picked up before prompt",
348.  						20, SET_IN_GAME },
349.  	{ "pickup_types", "types of objects to pick up automatically",
350.  						MAXOCLASSES, SET_IN_GAME },
351.  	{ "player_selection", "choose character via dialog or prompts",
352.  						12, DISP_IN_GAME },
353.  	{ "race",     "your starting race (e.g., Human, Elf)",
354.  						PL_CSIZ, DISP_IN_GAME },
355.  	{ "role",     "your starting role (e.g., Barbarian, Valkyrie)",
356.  						PL_CSIZ, DISP_IN_GAME },
357.  	{ "runmode", "display frequency when `running' or `travelling'",
358.  						sizeof "teleport", SET_IN_GAME },
359.  	{ "scores",   "the parts of the score list you wish to see",
360.  						32, SET_IN_GAME },
361.  	{ "scroll_amount", "amount to scroll map when scroll_margin is reached",
362.  						20, DISP_IN_GAME }, /*WC*/
363.  	{ "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
364.  #ifdef MSDOS
365.  	{ "soundcard", "type of sound card to use", 20, SET_IN_FILE },
366.  #endif
367.  	{ "suppress_alert", "suppress alerts about version-specific features",
368.  						8, SET_IN_GAME },
369.  	{ "tile_width", "width of tiles", 20, DISP_IN_GAME},	/*WC*/
370.  	{ "tile_height", "height of tiles", 20, DISP_IN_GAME},	/*WC*/
371.  	{ "tile_file", "name of tile file", 70, DISP_IN_GAME},	/*WC*/
372.  	{ "tileset",  "name of predefined tileset to use",
373.  						PL_PSIZ, SET_IN_GAME },
374.  	{ "traps",    "the symbols to use in drawing traps",
375.  						MAXTCHARS+1, SET_IN_FILE },
376.  	{ "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/
377.  #ifdef MSDOS
378.  	{ "video",    "method of video updating", 20, SET_IN_FILE },
379.  #endif
380.  #ifdef VIDEOSHADES
381.  	{ "videocolors", "color mappings for internal screen routines",
382.  						40, DISP_IN_GAME },
383.  #ifdef MSDOS
384.  	{ "videoshades", "gray shades to map to black/gray/white",
385.  						32, DISP_IN_GAME },
386.  #endif
387.  #endif
388.  #ifdef WIN32CON
389.  	{"subkeyvalue", "override keystroke value", 7, SET_IN_FILE},
390.  #endif
391.  	{ "windowcolors",  "the foreground/background colors of windows",	/*WC*/
392.  						80, DISP_IN_GAME },
393.  	{ "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
394.  	{ "wolfname",  "the name of your (first) wolf (e.g., wolfname:Beast)",
395.  						PL_PSIZ, DISP_IN_GAME },
396.  	{ (char *)0, (char *)0, 0, 0 }
397.  };
398.  
399.  static struct Bool_Tile_Opt
400.  {
401.  	const char *name;
402.  	unsigned long flag;
403.  	unsigned long initvalue;
404.  } booltileopt[] = {
405.  	{"transparent", TILESET_TRANSPARENT, 0},
406.  	{"pseudo3D", TILESET_PSEUDO3D, 0},
407.  	{(char *)0, 0, 0}
408.  };
409.  
410.  #ifdef OPTION_LISTS_ONLY
411.  #undef static
412.  
413.  #else	/* use rest of file */
414.  
415.  static boolean need_redraw; /* for doset() */
416.  
417.  #if defined(TOS) && defined(TEXTCOLOR)
418.  extern boolean colors_changed;	/* in tos.c */
419.  #endif
420.  
421.  #ifdef VIDEOSHADES
422.  extern char *shade[3];		  /* in sys/msdos/video.c */
423.  extern char ttycolors[CLR_MAX];	  /* in sys/msdos/video.c, win/tty/termcap.c*/
424.  #endif
425.  
426.  static char def_inv_order[MAXOCLASSES] = {
427.  	COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
428.  	SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
429.  	TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
430.  };
431.  
432.  /*
433.   * Default menu manipulation command accelerators.  These may _not_ be:
434.   *
435.   *	+ a number - reserved for counts
436.   *	+ an upper or lower case US ASCII letter - used for accelerators
437.   *	+ ESC - reserved for escaping the menu
438.   *	+ NULL, CR or LF - reserved for commiting the selection(s).  NULL
439.   *	  is kind of odd, but the tty's xwaitforspace() will return it if
440.   *	  someone hits a <ret>.
441.   *	+ a default object class symbol - used for object class accelerators
442.   *
443.   * Standard letters (for now) are:
444.   *
445.   *		<  back 1 page
446.   *		>  forward 1 page
447.   *		^  first page
448.   *		|  last page
449.   *		:  search
450.   *
451.   *		page		all
452.   *		 ,    select	 .
453.   *		 \    deselect	 -
454.   *		 ~    invert	 @
455.   *
456.   * The command name list is duplicated in the compopt array.
457.   */
458.  typedef struct {
459.      const char *name;
460.      char cmd;
461.  } menu_cmd_t;
462.  
463.  #define NUM_MENU_CMDS 11
464.  static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
465.  /* 0*/	{ "menu_first_page",	MENU_FIRST_PAGE },
466.  	{ "menu_last_page",	MENU_LAST_PAGE },
467.  	{ "menu_next_page",	MENU_NEXT_PAGE },
468.  	{ "menu_previous_page",	MENU_PREVIOUS_PAGE },
469.  	{ "menu_select_all",	MENU_SELECT_ALL },
470.  /* 5*/	{ "menu_deselect_all",	MENU_UNSELECT_ALL },
471.  	{ "menu_invert_all",	MENU_INVERT_ALL },
472.  	{ "menu_select_page",	MENU_SELECT_PAGE },
473.  	{ "menu_deselect_page",	MENU_UNSELECT_PAGE },
474.  	{ "menu_invert_page",	MENU_INVERT_PAGE },
475.  /*10*/	{ "menu_search",		MENU_SEARCH },
476.  };
477.  
478.  /*
479.   * Allow the user to map incoming characters to various menu commands.
480.   * The accelerator list must be a valid C string.
481.   */
482.  #define MAX_MENU_MAPPED_CMDS 32	/* some number */
483.         char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1];	/* exported */
484.  static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1];
485.  static short n_menu_mapped = 0;
486.  
487.  static boolean initial, from_file;
488.  
489.  STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int));
490.  STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
491.  STATIC_DCL void FDECL(escapes, (const char *, char *));
492.  STATIC_DCL void FDECL(rejectoption, (const char *));
493.  STATIC_DCL void FDECL(badoption, (const char *));
494.  STATIC_OVL void FDECL(badtileoption, (const char *));
495.  STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P));
496.  STATIC_OVL char *FDECL(string_for_tile_opt, (char *, BOOLEAN_P));
497.  STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *,BOOLEAN_P));
498.  STATIC_DCL void FDECL(bad_negation, (const char *,BOOLEAN_P));
499.  STATIC_DCL int FDECL(change_inv_order, (char *));
500.  STATIC_DCL void FDECL(oc_to_str, (char *, char *));
501.  STATIC_DCL void FDECL(graphics_opts, (char *,const char *,int,int));
502.  STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
503.  STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
504.  STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P));
505.  STATIC_DCL void FDECL(warning_opts, (char *,const char *));
506.  STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int));
507.  
508.  STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
509.  STATIC_OVL int FDECL(wc_set_window_colors, (char *));
510.  STATIC_OVL boolean FDECL(is_wc_option, (const char *));
511.  STATIC_OVL boolean FDECL(wc_supported, (const char *));
512.  STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
513.  STATIC_OVL boolean FDECL(wc2_supported, (const char *));
514.  #ifdef AUTOPICKUP_EXCEPTIONS
515.  STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *));
516.  STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
517.  #endif
518.  
519.  /* check whether a user-supplied option string is a proper leading
520.     substring of a particular option name; option string might have
521.     a colon or equals sign and arbitrary value appended to it */
522.  boolean
523.  match_optname(user_string, opt_name, min_length, val_allowed)
524.  const char *user_string, *opt_name;
525.  int min_length;
526.  boolean val_allowed;
527.  {
528.  	int len = (int)strlen(user_string);
529.  
530.  	if (val_allowed) {
531.  	    const char *p = index(user_string, ':'),
532.  		       *q = index(user_string, '=');
533.  
534.  	    if (!p || (q && q < p)) p = q;
535.  	    while(p && p > user_string && isspace(*(p-1))) p--;
536.  	    if (p) len = (int)(p - user_string);
537.  	}
538.  
539.  	return (len >= min_length) && !strncmpi(opt_name, user_string, len);
540.  }
541.  
542.  /* most environment variables will eventually be printed in an error
543.   * message if they don't work, and most error message paths go through
544.   * BUFSZ buffers, which could be overflowed by a maliciously long
545.   * environment variable.  if a variable can legitimately be long, or
546.   * if it's put in a smaller buffer, the responsible code will have to
547.   * bounds-check itself.
548.   */
549.  char *
550.  nh_getenv(ev)
551.  const char *ev;
552.  {
553.  	char *getev = getenv(ev);
554.  
555.  	if (getev && strlen(getev) <= (BUFSZ / 2))
556.  		return getev;
557.  	else
558.  		return (char *)0;
559.  }
560.  
561.  void
562.  initoptions()
563.  {
564.  #ifndef MAC
565.  	char *opts;
566.  #endif
567.  	int i;
568.  
569.  	/* initialize the random number generator */
570.  	setrandom();
571.  
572.  	/* for detection of configfile options specified multiple times */
573.  	iflags.opt_booldup = iflags.opt_compdup = (int *)0;
574.  	
575.  	for (i = 0; boolopt[i].name; i++) {
576.  		if (boolopt[i].addr)
577.  			*(boolopt[i].addr) = boolopt[i].initvalue;
578.  	}
579.  	flags.end_own = FALSE;
580.  	flags.end_top = 3;
581.  	flags.end_around = 2;
582.  	iflags.runmode = RUN_LEAP;
583.  	iflags.msg_history = 20;
584.  #ifdef TTY_GRAPHICS
585.  	iflags.prevmsg_window = 's';
586.  #endif
587.  	iflags.menu_headings = ATR_INVERSE;
588.  
589.  	/* Use negative indices to indicate not yet selected */
590.  	flags.initrole = -1;
591.  	flags.initrace = -1;
592.  	flags.initgend = -1;
593.  	flags.initalign = -1;
594.  
595.  	/* Set the default monster and object class symbols.  Don't use */
596.  	/* memcpy() --- sizeof char != sizeof uchar on some machines.	*/
597.  	for (i = 0; i < MAXOCLASSES; i++)
598.  		oc_syms[i] = (uchar) def_oc_syms[i];
599.  	for (i = 0; i < MAXMCLASSES; i++)
600.  		monsyms[i] = (uchar) def_monsyms[i];
601.  	for (i = 0; i < WARNCOUNT; i++)
602.  		warnsyms[i] = def_warnsyms[i].sym;
603.  	iflags.bouldersym = 0;
604.  	iflags.travelcc.x = iflags.travelcc.y = -1;
605.  	flags.warnlevel = 1;
606.  	flags.warntype = 0L;
607.  
608.       /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
609.  	(void)memcpy((genericptr_t)flags.inv_order,
610.  		     (genericptr_t)def_inv_order, sizeof flags.inv_order);
611.  	flags.pickup_types[0] = '\0';
612.  	flags.pickup_burden = MOD_ENCUMBER;
613.  
614.  	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
615.  		flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
616.  	switch_graphics(ASCII_GRAPHICS);	/* set default characters */
617.  #if defined(UNIX) && defined(TTY_GRAPHICS)
618.  	/*
619.  	 * Set defaults for some options depending on what we can
620.  	 * detect about the environment's capabilities.
621.  	 * This has to be done after the global initialization above
622.  	 * and before reading user-specific initialization via
623.  	 * config file/environment variable below.
624.  	 */
625.  	/* this detects the IBM-compatible console on most 386 boxes */
626.  	if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
627.  		switch_graphics(IBM_GRAPHICS);
628.  # ifdef TEXTCOLOR
629.  		iflags.use_color = TRUE;
630.  # endif
631.  	}
632.  #endif /* UNIX && TTY_GRAPHICS */
633.  #if defined(UNIX) || defined(VMS)
634.  # ifdef TTY_GRAPHICS
635.  	/* detect whether a "vt" terminal can handle alternate charsets */
636.  	if ((opts = nh_getenv("TERM")) &&
637.  	    !strncmpi(opts, "vt", 2) && AS && AE &&
638.  	    index(AS, '\016') && index(AE, '\017')) {
639.  		switch_graphics(DEC_GRAPHICS);
640.  	}
641.  # endif
642.  #endif /* UNIX || VMS */
643.  
644.  #ifdef MAC_GRAPHICS_ENV
645.  	switch_graphics(MAC_GRAPHICS);
646.  #endif /* MAC_GRAPHICS_ENV */
647.  	flags.menu_style = MENU_FULL;
648.  
649.  	/* since this is done before init_objects(), do partial init here */
650.  	objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
651.  	nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
652.  #ifndef MAC
653.  	opts = getenv(NETHACK_ENV_OPTIONS);
654.  	if (!opts) opts = getenv("NETHACKOPTIONS");
655.  	if (!opts) opts = getenv("HACKOPTIONS");
656.  	if (opts) {
657.  		if (*opts == '/' || *opts == '\\' || *opts == '@') {
658.  			if (*opts == '@') opts++;	/* @filename */
659.  			/* looks like a filename */
660.  			if (strlen(opts) < BUFSZ/2)
661.  			    read_config_file(opts);
662.  		} else {
663.  			read_config_file((char *)0);
664.  			/* let the total length of options be long;
665.  			 * parseoptions() will check each individually
666.  			 */
667.  			parseoptions(opts, TRUE, FALSE);
668.  		}
669.  	} else
670.  #endif
671.  		read_config_file((char *)0);
672.  
673.  	(void)fruitadd(pl_fruit);
674.  	/* Remove "slime mold" from list of object names; this will	*/
675.  	/* prevent it from being wished unless it's actually present	*/
676.  	/* as a named (or default) fruit.  Wishing for "fruit" will	*/
677.  	/* result in the player's preferred fruit [better than "\033"].	*/
678.  	obj_descr[SLIME_MOLD].oc_name = "fruit";
679.  
680.  #if defined(GL_GRAPHICS) || defined(SDL_GRAPHICS)
681.  	/* -AJA- SDL/GL support.  Needs to happen after main config
682.  	 *       file has been read.
683.  	 */
684.  	opts = getenv(SDLGL_ENV_VAR);
685.  	if (opts)
686.  		Sdlgl_parse_options(opts, TRUE, FALSE);
687.  #endif
688.  
689.  	return;
690.  }
691.  
692.  STATIC_OVL void
693.  nmcpy(dest, src, maxlen)
694.  	char	*dest;
695.  	const char *src;
696.  	int	maxlen;
697.  {
698.  	int	count;
699.  
700.  	for(count = 1; count < maxlen; count++) {
701.  		if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
702.  		*dest++ = *src++;
703.  	}
704.  	*dest = 0;
705.  }
706.  
707.  /*
708.   * escapes: escape expansion for showsyms. C-style escapes understood include
709.   * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
710.   * for control characters is also understood, and \[mM] followed by any of the
711.   * previous forms or by a character has the effect of 'meta'-ing the value (so
712.   * that the alternate character set will be enabled).
713.   */
714.  STATIC_OVL void
715.  escapes(cp, tp)
716.  const char	*cp;
717.  char *tp;
718.  {
719.      while (*cp)
720.      {
721.  	int	cval = 0, meta = 0;
722.  
723.  	if (*cp == '\\' && index("mM", cp[1])) {
724.  		meta = 1;
725.  		cp += 2;
726.  	}
727.  	if (*cp == '\\' && index("0123456789xXoO", cp[1]))
728.  	{
729.  	    const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
730.  	    int dcount = 0;
731.  
732.  	    cp++;
733.  	    if (*cp == 'x' || *cp == 'X')
734.  		for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
735.  		    cval = (cval * 16) + (dp - hex) / 2;
736.  	    else if (*cp == 'o' || *cp == 'O')
737.  		for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
738.  		    cval = (cval * 8) + (*cp - '0');
739.  	    else
740.  		for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
741.  		    cval = (cval * 10) + (*cp - '0');
742.  	}
743.  	else if (*cp == '\\')		/* C-style character escapes */
744.  	{
745.  	    switch (*++cp)
746.  	    {
747.  	    case '\\': cval = '\\'; break;
748.  	    case 'n': cval = '\n'; break;
749.  	    case 't': cval = '\t'; break;
750.  	    case 'b': cval = '\b'; break;
751.  	    case 'r': cval = '\r'; break;
752.  	    default: cval = *cp;
753.  	    }
754.  	    cp++;
755.  	}
756.  	else if (*cp == '^')		/* expand control-character syntax */
757.  	{
758.  	    cval = (*++cp & 0x1f);
759.  	    cp++;
760.  	}
761.  	else
762.  	    cval = *cp++;
763.  	if (meta)
764.  	    cval |= 0x80;
765.  	*tp++ = cval;
766.      }
767.      *tp = '\0';
768.  }
769.  
770.  STATIC_OVL void
771.  rejectoption(optname)
772.  const char *optname;
773.  {
774.  #ifdef MICRO
775.  	pline("\"%s\" settable only from %s.", optname, configfile);
776.  #else
777.  	pline("%s can be set only from %s or %s.", optname,
778.  			NETHACK_ENV_OPTIONS, configfile);
779.  #endif
780.  }
781.  
782.  STATIC_OVL void
783.  badoption(opts)
784.  const char *opts;
785.  {
786.  	if (!initial) {
787.  	    if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
788.  		option_help();
789.  	    else
790.  		pline("Bad syntax: %s.  Enter \"?g\" for help.", opts);
791.  	    return;
792.  	}
793.  #ifdef MAC
794.  	else return;
795.  #endif
796.  
797.  	if(from_file)
798.  	    raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
799.  	else
800.  	    raw_printf("Bad syntax in %s: %s.", NETHACK_ENV_OPTIONS, opts);
801.  
802.  	wait_synch();
803.  }
804.  
805.  STATIC_OVL void
806.  badauthoption(opts)
807.  const char *opts;
808.  {
809.  	raw_printf("Bad syntax in AUTHENTICATION in %s: %s.", configfile, opts);
810.  	wait_synch();
811.  }
812.  
813.  STATIC_OVL void
814.  badtileoption(opts)
815.  const char *opts;
816.  {
817.  	raw_printf("Bad syntax in TILESET in %s: %s.", configfile, opts);
818.  	wait_synch();
819.  }
820.  
821.  STATIC_OVL char *
822.  string_for_opt(opts, val_optional)
823.  char *opts;
824.  boolean val_optional;
825.  {
826.  	char *colon, *equals;
827.  
828.  	colon = index(opts, ':');
829.  	equals = index(opts, '=');
830.  	if (!colon || (equals && equals < colon)) colon = equals;
831.  
832.  	if (!colon || !*++colon) {
833.  		if (!val_optional) badoption(opts);
834.  		return (char *)0;
835.  	}
836.  	return colon;
837.  }
838.  
839.  STATIC_OVL char *
840.  string_for_auth_opt(opts, val_optional)
841.  char *opts;
842.  boolean val_optional;
843.  {
844.  	char *colon = string_for_opt(opts, TRUE);
845.  	if (!colon && !val_optional) badauthoption(opts);
846.  	return colon;
847.  }
848.  
849.  STATIC_OVL char *
850.  string_for_tile_opt(opts, val_optional)
851.  char *opts;
852.  boolean val_optional;
853.  {
854.  	char *colon = string_for_opt(opts, TRUE);
855.  	if (!colon && !val_optional) badtileoption(opts);
856.  	return colon;
857.  }
858.  
859.  STATIC_OVL char *
860.  string_for_env_opt(optname, opts, val_optional)
861.  const char *optname;
862.  char *opts;
863.  boolean val_optional;
864.  {
865.  	if(!initial) {
866.  		rejectoption(optname);
867.  		return (char *)0;
868.  	}
869.  	return string_for_opt(opts, val_optional);
870.  }
871.  
872.  STATIC_OVL void
873.  bad_negation(optname, with_parameter)
874.  const char *optname;
875.  boolean with_parameter;
876.  {
877.  	pline_The("%s option may not %sbe negated.",
878.  		optname,
879.  		with_parameter ? "both have a value and " : "");
880.  }
881.  
882.  /*
883.   * Change the inventory order, using the given string as the new order.
884.   * Missing characters in the new order are filled in at the end from
885.   * the current inv_order, except for gold, which is forced to be first
886.   * if not explicitly present.
887.   *
888.   * This routine returns 1 unless there is a duplicate or bad char in
889.   * the string.
890.   */
891.  STATIC_OVL int
892.  change_inv_order(op)
893.  char *op;
894.  {
895.      int oc_sym, num;
896.      char *sp, buf[BUFSZ];
897.  
898.      num = 0;
899.  #ifndef GOLDOBJ
900.      if (!index(op, GOLD_SYM))
901.  	buf[num++] = COIN_CLASS;
902.  #else
903.      /*  !!!! probably unnecessary with gold as normal inventory */
904.  #endif
905.  
906.      for (sp = op; *sp; sp++) {
907.  	oc_sym = def_char_to_objclass(*sp);
908.  	/* reject bad or duplicate entries */
909.  	if (oc_sym == MAXOCLASSES ||
910.  		oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS ||
911.  		!index(flags.inv_order, oc_sym) || index(sp+1, *sp))
912.  	    return 0;
913.  	/* retain good ones */
914.  	buf[num++] = (char) oc_sym;
915.      }
916.      buf[num] = '\0';
917.  
918.      /* fill in any omitted classes, using previous ordering */
919.      for (sp = flags.inv_order; *sp; sp++)
920.  	if (!index(buf, *sp)) {
921.  	    buf[num++] = *sp;
922.  	    buf[num] = '\0';	/* explicitly terminate for next index() */
923.  	}
924.  
925.      Strcpy(flags.inv_order, buf);
926.      return 1;
927.  }
928.  
929.  STATIC_OVL void
930.  graphics_opts(opts, optype, maxlen, offset)
931.  register char *opts;
932.  const char *optype;
933.  int maxlen, offset;
934.  {
935.  	uchar translate[MAXPCHARS+1];
936.  	int length, i;
937.  
938.  	if (!(opts = string_for_env_opt(optype, opts, FALSE)))
939.  		return;
940.  	escapes(opts, opts);
941.  
942.  	length = strlen(opts);
943.  	if (length > maxlen) length = maxlen;
944.  	/* match the form obtained from PC configuration files */
945.  	for (i = 0; i < length; i++)
946.  		translate[i] = (uchar) opts[i];
947.  	assign_graphics(translate, length, maxlen, offset);
948.  }
949.  
950.  STATIC_OVL void
951.  warning_opts(opts, optype)
952.  register char *opts;
953.  const char *optype;
954.  {
955.  	uchar translate[MAXPCHARS+1];
956.  	int length, i;
957.  
958.  	if (!(opts = string_for_env_opt(optype, opts, FALSE)))
959.  		return;
960.  	escapes(opts, opts);
961.  
962.  	length = strlen(opts);
963.  	if (length > WARNCOUNT) length = WARNCOUNT;
964.  	/* match the form obtained from PC configuration files */
965.  	for (i = 0; i < length; i++)
966.  	     translate[i] = (((i < WARNCOUNT) && opts[i]) ?
967.  			   (uchar) opts[i] : def_warnsyms[i].sym);
968.  	assign_warnings(translate);
969.  }
970.  
971.  void
972.  assign_warnings(graph_chars)
973.  register uchar *graph_chars;
974.  {
975.  	int i;
976.  	for (i = 0; i < WARNCOUNT; i++)
977.  	    if (graph_chars[i]) warnsyms[i] = graph_chars[i];
978.  }
979.  
980.  STATIC_OVL int
981.  feature_alert_opts(op, optn)
982.  char *op;
983.  const char *optn;
984.  {
985.  	char buf[BUFSZ];
986.  	boolean rejectver = FALSE;
987.  	unsigned long fnv = get_feature_notice_ver(op);		/* version.c */
988.  	if (fnv == 0L) return 0;
989.  	if (fnv > get_current_feature_ver())
990.  		rejectver = TRUE;
991.  	else
992.  		flags.suppress_alert = fnv;
993.  	if (rejectver) {
994.  		if (!initial)
995.  			You_cant("disable new feature alerts for future versions.");
996.  		else {
997.  			Sprintf(buf,
998.  				"\n%s=%s Invalid reference to a future version ignored",
999.  				optn, op);
1000. 			badoption(buf);
1001. 		}
1002. 		return 0;
1003. 	}
1004. 	if (!initial) {
1005. 		Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
1006. 			FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
1007. 		pline("Feature change alerts disabled for Slash'EM %s features and prior.",
1008. 			buf);
1009. 	}
1010. 	return 1;
1011. }
1012. 
1013. void
1014. set_duplicate_opt_detection(on_or_off)
1015. int on_or_off;
1016. {
1017. 	int k, *optptr;
1018. 	if (on_or_off != 0) {
1019. 		/*-- ON --*/
1020. 		if (iflags.opt_booldup)
1021. 			impossible("iflags.opt_booldup already on (memory leak)");
1022. 		iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int));
1023. 		optptr = iflags.opt_booldup;
1024. 		for (k = 0; k < SIZE(boolopt); ++k)
1025. 			*optptr++ = 0;
1026. 			
1027. 		if (iflags.opt_compdup)
1028. 			impossible("iflags.opt_compdup already on (memory leak)");
1029. 		iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int));
1030. 		optptr = iflags.opt_compdup;
1031. 		for (k = 0; k < SIZE(compopt); ++k)
1032. 			*optptr++ = 0;
1033. 	} else {
1034. 		/*-- OFF --*/
1035. 		if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup);
1036. 		iflags.opt_booldup = (int *)0;
1037. 		if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup);
1038. 		iflags.opt_compdup = (int *)0;
1039. 	} 
1040. }
1041. 
1042. STATIC_OVL void
1043. duplicate_opt_detection(opts, bool_or_comp)
1044. const char *opts;
1045. int bool_or_comp;	/* 0 == boolean option, 1 == compound */
1046. {
1047. 	int i, *optptr;
1048. #if defined(MAC)
1049. 	/* the Mac has trouble dealing with the output of messages while
1050. 	 * processing the config file.  That should get fixed one day.
1051. 	 * For now just return.
1052. 	 */
1053. 	return;
1054. #endif
1055. 	if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) {
1056. 	    for (i = 0; boolopt[i].name; i++) {
1057. 		if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1058. 			optptr = iflags.opt_booldup + i;
1059. 			if (*optptr == 1) {
1060. 			    raw_printf(
1061. 				"\nWarning - Boolean option specified multiple times: %s.\n",
1062. 					opts);
1063. 			        wait_synch();
1064. 			}
1065. 			*optptr += 1;
1066. 			break; /* don't match multiple options */
1067. 		}
1068. 	    }
1069. 	} else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) {
1070. 	    for (i = 0; compopt[i].name; i++) {
1071. 		if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) {
1072. 			optptr = iflags.opt_compdup + i;
1073. 			if (*optptr == 1) {
1074. 			    raw_printf(
1075. 				"\nWarning - compound option specified multiple times: %s.\n",
1076. 					compopt[i].name);
1077. 			        wait_synch();
1078. 			}
1079. 			*optptr += 1;
1080. 			break; /* don't match multiple options */
1081. 		}
1082. 	    }
1083. 	}
1084. }
1085. 
1086. #ifdef MENU_COLOR
1087. extern struct menucoloring *menu_colorings;
1088. 
1089. static const struct {
1090.    const char *name;
1091.    const int color;
1092. } colornames[] = {
1093.    {"black", CLR_BLACK},
1094.    {"red", CLR_RED},
1095.    {"green", CLR_GREEN},
1096.    {"brown", CLR_BROWN},
1097.    {"blue", CLR_BLUE},
1098.    {"magenta", CLR_MAGENTA},
1099.    {"cyan", CLR_CYAN},
1100.    {"gray", CLR_GRAY},
1101.    {"orange", CLR_ORANGE},
1102.    {"lightgreen", CLR_BRIGHT_GREEN},
1103.    {"yellow", CLR_YELLOW},
1104.    {"lightblue", CLR_BRIGHT_BLUE},
1105.    {"lightmagenta", CLR_BRIGHT_MAGENTA},
1106.    {"lightcyan", CLR_BRIGHT_CYAN},
1107.    {"white", CLR_WHITE}
1108. };
1109. 
1110. static const struct {
1111.    const char *name;
1112.    const int attr;
1113. } attrnames[] = {
1114.      {"none", ATR_NONE},
1115.      {"bold", ATR_BOLD},
1116.      {"dim", ATR_DIM},
1117.      {"underline", ATR_ULINE},
1118.      {"blink", ATR_BLINK},
1119.      {"inverse", ATR_INVERSE}
1120. 
1121. };
1122. 
1123. /* parse '"regex_string"=color' and add it to menucoloring */
1124. boolean
1125. add_menu_coloring(str)
1126. char *str;
1127. {
1128.    int i, c = NO_COLOR, a = ATR_NONE;
1129.    struct menucoloring *tmp;
1130.    char *tmps, *cs = strchr(str, '=');
1131. #ifdef POSIX_REGEX
1132.    int errnum;
1133.    char errbuf[80];
1134. #endif
1135.    const char *err = (char *)0;
1136.    
1137.    if (!cs || !str) return FALSE;
1138.    
1139.    tmps = cs;
1140.    tmps++;
1141.    while (*tmps && isspace(*tmps)) tmps++;
1142. 
1143.    for (i = 0; i < SIZE(colornames); i++)
1144.      if (strstri(tmps, colornames[i].name) == tmps) {
1145. 	c = colornames[i].color;
1146. 	break;
1147.      }
1148.    if ((i == SIZE(colornames)) && (*tmps >= '0' && *tmps <='9'))
1149.      c = atoi(tmps);
1150.    
1151.    if (c > 15) return FALSE;
1152.    
1153.    tmps = strchr(str, '&');
1154.    if (tmps) {
1155.       tmps++;
1156.       while (*tmps && isspace(*tmps)) tmps++;
1157.       for (i = 0; i < SIZE(attrnames); i++)
1158. 	if (strstri(tmps, attrnames[i].name) == tmps) {
1159. 	   a = attrnames[i].attr;
1160. 	   break;
1161. 	}
1162.       if ((i == SIZE(attrnames)) && (*tmps >= '0' && *tmps <='9'))
1163. 	a = atoi(tmps);
1164.    }
1165.    
1166.    *cs = '\0';
1167.    tmps = str;
1168.    if ((*tmps == '"') || (*tmps == '\)) {
1169.       cs--;
1170.       while (isspace(*cs)) cs--;
1171.       if (*cs == *tmps) {
1172. 	 *cs = '\0';
1173. 	 tmps++;
1174.       }
1175.    }
1176.    
1177.    tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring));
1178. #ifdef USE_REGEX_MATCH
1179. # ifdef GNU_REGEX
1180.    tmp->match.translate = 0;
1181.    tmp->match.fastmap = 0;
1182.    tmp->match.buffer = 0;
1183.    tmp->match.allocated = 0;
1184.    tmp->match.regs_allocated = REGS_FIXED;
1185.    err = re_compile_pattern(tmps, strlen(tmps), &tmp->match);
1186. # else
1187. #  ifdef POSIX_REGEX
1188.    errnum = regcomp(&tmp->match, tmps, REG_EXTENDED | REG_NOSUB);
1189.    if (errnum != 0) {                                                                                                                                                                                                               
1190.       regerror(errnum, &tmp->match, errbuf, sizeof(errbuf));
1191.       err = errbuf;
1192.    }
1193. #  endif  
1194. # endif  
1195. #else
1196.    tmp->match = (char *)alloc(strlen(tmps)+1);
1197.    (void) memcpy((genericptr_t)tmp->match, (genericptr_t)tmps, strlen(tmps)+1);
1198. #endif
1199.    if (err) {
1200.       raw_printf("\nMenucolor regex error: %s\n", err);
1201.       wait_synch();
1202.       free(tmp);
1203.       return FALSE;
1204.    } else {
1205.       tmp->next = menu_colorings;
1206.       tmp->color = c;
1207.       tmp->attr = a;
1208.       menu_colorings = tmp;
1209.       return TRUE;
1210.    }
1211. }
1212. #endif /* MENU_COLOR */
1213. 
1214. void
1215. parseoptions(opts, tinitial, tfrom_file)
1216. register char *opts;
1217. boolean tinitial, tfrom_file;
1218. {
1219. 	register char *op;
1220. 	unsigned num;
1221. 	boolean negated;
1222. 	int i;
1223. 	const char *fullname;
1224. 
1225. 	initial = tinitial;
1226. 	from_file = tfrom_file;
1227. 	if ((op = index(opts, ',')) != 0) {
1228. 		*op++ = 0;
1229. 		parseoptions(op, initial, from_file);
1230. 	}
1231. 	if (strlen(opts) > BUFSZ/2) {
1232. 		badoption("option too long");
1233. 		return;
1234. 	}
1235. 
1236. 	/* strip leading and trailing white space */
1237. 	while (isspace((int)*opts)) opts++;
1238. 	op = eos(opts);
1239. 	while (--op >= opts && isspace((int)*op)) *op = '\0';
1240. 
1241. 	if (!*opts) return;
1242. 	negated = FALSE;
1243. 	while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
1244. 		if (*opts == '!') opts++; else opts += 2;
1245. 		negated = !negated;
1246. 	}
1247. 
1248. 	/* variant spelling */
1249. 
1250. 	if (match_optname(opts, "colour", 5, FALSE))
1251. 		Strcpy(opts, "color");	/* fortunately this isn't longer */
1252. 
1253. 	if (!match_optname(opts, "subkeyvalue", 11, TRUE)) /* allow multiple */
1254. 	duplicate_opt_detection(opts, 1);	/* 1 means compound opts */
1255. 
1256. 	/* special boolean options */
1257. 
1258. 	if (match_optname(opts, "female", 3, FALSE)) {
1259. 		if(!initial && flags.female == negated)
1260. 			pline("That is not anatomically possible.");
1261. 		else
1262. 			flags.initgend = flags.female = !negated;
1263. 		return;
1264. 	}
1265. 
1266. 	if (match_optname(opts, "male", 4, FALSE)) {
1267. 		if(!initial && flags.female != negated)
1268. 			pline("That is not anatomically possible.");
1269. 		else
1270. 			flags.initgend = flags.female = negated;
1271. 		return;
1272. 	}
1273. 
1274. #if defined(MICRO) && !defined(AMIGA)
1275. 	/* included for compatibility with old NetHack.cnf files */
1276. 	if (match_optname(opts, "IBM_", 4, FALSE)) {
1277. 		iflags.BIOS = !negated;
1278. 		return;
1279. 	}
1280. #endif /* MICRO */
1281. 
1282. 	/* compound options */
1283. 
1284. 	fullname = "pettype";
1285. 	if (match_optname(opts, fullname, 3, TRUE)) {
1286. 		if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
1287. 		    if (negated) bad_negation(fullname, TRUE);
1288. 		    else switch (*op) {
1289. 			case 'd':	/* dog */
1290. 			case 'D':
1291. 			    preferred_pet = 'd';
1292. 			    break;
1293. 			case 'c':	/* cat */
1294. 			case 'C':
1295. 			case 'f':	/* feline */
1296. 			case 'F':
1297. 			    preferred_pet = 'c';
1298. 			    break;
1299. 			case 'n':	/* no pet */
1300. 			case 'N':
1301. 			    preferred_pet = 'n';
1302. 			    break;
1303. 			default:
1304. 			    pline("Unrecognized pet type '%s'.", op);
1305. 			    break;
1306. 		    }
1307. 		} else if (negated) preferred_pet = 'n';
1308. 		return;
1309. 	}
1310. 
1311.         fullname = "ghoulname";
1312. 	if (match_optname(opts, fullname, 3, TRUE)) {
1313. 		if (negated) bad_negation(fullname, FALSE);
1314. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1315.                         nmcpy(ghoulname, op, PL_PSIZ);
1316. 		return;
1317. 	}
1318. 
1319.         fullname = "wolfname";
1320. 	if (match_optname(opts, fullname, 3, TRUE)) {
1321. 		if (negated) bad_negation(fullname, FALSE);
1322. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1323.                         nmcpy(wolfname, op, PL_PSIZ);
1324. 		return;
1325. 	}
1326. 
1327. 	fullname = "catname";
1328. 	if (match_optname(opts, fullname, 3, TRUE)) {
1329. 		if (negated) bad_negation(fullname, FALSE);
1330. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1331. 			nmcpy(catname, op, PL_PSIZ);
1332. 		return;
1333. 	}
1334. 
1335. 	fullname = "dogname";
1336. 	if (match_optname(opts, fullname, 3, TRUE)) {
1337. 		if (negated) bad_negation(fullname, FALSE);
1338. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1339. 			nmcpy(dogname, op, PL_PSIZ);
1340. 		return;
1341. 	}
1342. 
1343. 	fullname = "horsename";
1344. 	if (match_optname(opts, fullname, 5, TRUE)) {
1345. 		if (negated) bad_negation(fullname, FALSE);
1346. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1347. 			nmcpy(horsename, op, PL_PSIZ);
1348. 		return;
1349. 	}
1350. 
1351. 	/* menucolor:"regex_string"=color */
1352. 	fullname = "menucolor";
1353. 	if (match_optname(opts, fullname, 9, TRUE)) {
1354. #ifdef MENU_COLOR
1355. 		if (negated) bad_negation(fullname, FALSE);
1356. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1357. 			if (!add_menu_coloring(op))
1358. 				badoption(opts);
1359. #endif
1360.  		return;
1361.  	}
1362. 
1363. 	fullname = "number_pad";
1364. 	if (match_optname(opts, fullname, 10, TRUE)) {
1365. 		boolean compat = (strlen(opts) <= 10);
1366. 		op = string_for_opt(opts, (compat || !initial));
1367. 		if (!op) {
1368. 		    if (compat || negated || initial) {
1369. 			/* for backwards compatibility, "number_pad" without a
1370. 			   value is a synonym for number_pad:1 */
1371. 			iflags.num_pad = !negated;
1372. 			if (iflags.num_pad) iflags.num_pad_mode = 0;
1373. 			number_pad(iflags.num_pad);
1374. 		    }
1375. 		    return;
1376. 		}
1377. 		if (negated) {
1378. 		    bad_negation("number_pad", TRUE);
1379. 		    return;
1380. 		}
1381. 		if (*op == '1' || *op == '2') {
1382. 			iflags.num_pad = 1;
1383. 			if (*op == '2') iflags.num_pad_mode = 1;
1384. 			else iflags.num_pad_mode = 0;
1385. 			number_pad(1);
1386. 		} else if (*op == '0') {
1387. 			iflags.num_pad = 0;
1388. 			iflags.num_pad_mode = 0;
1389. 			number_pad(0);
1390. 		} else badoption(opts);
1391. 		return;
1392. 	}
1393. 
1394. 	fullname = "runmode";
1395. 	if (match_optname(opts, fullname, 4, TRUE)) {
1396. 		if (negated) {
1397. 			iflags.runmode = RUN_TPORT;
1398. 		} else if ((op = string_for_opt(opts, FALSE)) != 0) {
1399. 		    if (!strncmpi(op, "teleport", strlen(op)))
1400. 			iflags.runmode = RUN_TPORT;
1401. 		    else if (!strncmpi(op, "run", strlen(op)))
1402. 			iflags.runmode = RUN_LEAP;
1403. 		    else if (!strncmpi(op, "walk", strlen(op)))
1404. 			iflags.runmode = RUN_STEP;
1405. 		    else if (!strncmpi(op, "crawl", strlen(op)))
1406. 			iflags.runmode = RUN_CRAWL;
1407. 		    else
1408. 			badoption(opts);
1409. 		}
1410. 		return;
1411. 	}
1412. 
1413. 	fullname = "msghistory";
1414. 	if (match_optname(opts, fullname, 3, TRUE)) {
1415. 		op = string_for_env_opt(fullname, opts, negated);
1416. 		if ((negated && !op) || (!negated && op)) {
1417. 			iflags.msg_history = negated ? 0 : atoi(op);
1418. 		} else if (negated) bad_negation(fullname, TRUE);
1419. 		return;
1420. 	}
1421. 
1422. 	fullname="msg_window";
1423. 	/* msg_window:single, combo, full or reversed */
1424. 	if (match_optname(opts, fullname, 4, TRUE)) {
1425. 	/* allow option to be silently ignored by non-tty ports */
1426. #ifdef TTY_GRAPHICS
1427. 		int tmp;
1428. 		if (!(op = string_for_opt(opts, TRUE))) {
1429. 		    tmp = negated ? 's' : 'f';
1430. 		} else {
1431. 			  if (negated) {
1432. 			  	bad_negation(fullname, TRUE);
1433. 			  	return;
1434. 				  }
1435. 		    tmp = tolower(*op);
1436. 		}
1437. 		switch (tmp) {
1438. 			case 's':	/* single message history cycle (default if negated) */
1439. 				iflags.prevmsg_window = 's';
1440. 				break;
1441. 			case 'c':	/* combination: two singles, then full page reversed */
1442. 				iflags.prevmsg_window = 'c';
1443. 				break;
1444. 			case 'f':	/* full page (default if no opts) */
1445. 				iflags.prevmsg_window = 'f';
1446. 				break;
1447. 			case 'r':	/* full page (reversed) */
1448. 				iflags.prevmsg_window = 'r';
1449. 				break;
1450. 			default:
1451. 				badoption(opts);
1452. 		}
1453. #endif
1454. 		return;
1455. 	}
1456. 
1457. 	/* WINCAP
1458. 	 * setting font options  */
1459. 	fullname = "font";
1460. 	if (!strncmpi(opts, fullname, 4))
1461. 	{
1462. 		int wintype = -1;
1463. 		char *fontopts = opts + 4;
1464. 
1465. 		if (!strncmpi(fontopts, "map", 3) ||
1466. 		    !strncmpi(fontopts, "_map", 4))
1467. 			wintype = NHW_MAP;
1468. 		else if (!strncmpi(fontopts, "message", 7) ||
1469. 			 !strncmpi(fontopts, "_message", 8))
1470. 			wintype = NHW_MESSAGE;
1471. 		else if (!strncmpi(fontopts, "text", 4) ||
1472. 			 !strncmpi(fontopts, "_text", 5))
1473. 			wintype = NHW_TEXT;			
1474. 		else if (!strncmpi(fontopts, "menu", 4) ||
1475. 			 !strncmpi(fontopts, "_menu", 5))
1476. 			wintype = NHW_MENU;
1477. 		else if (!strncmpi(fontopts, "status", 6) ||
1478. 			 !strncmpi(fontopts, "_status", 7))
1479. 			wintype = NHW_STATUS;
1480. 		else if (!strncmpi(fontopts, "_size", 5)) {
1481. 			if (!strncmpi(fontopts, "_size_map", 8))
1482. 				wintype = NHW_MAP;
1483. 			else if (!strncmpi(fontopts, "_size_message", 12))
1484. 				wintype = NHW_MESSAGE;
1485. 			else if (!strncmpi(fontopts, "_size_text", 9))
1486. 				wintype = NHW_TEXT;
1487. 			else if (!strncmpi(fontopts, "_size_menu", 9))
1488. 				wintype = NHW_MENU;
1489. 			else if (!strncmpi(fontopts, "_size_status", 11))
1490. 				wintype = NHW_STATUS;
1491. 			else {
1492. 				badoption(opts);
1493. 				return;
1494. 			}
1495. 			if (wintype > 0 && !negated &&
1496. 			    (op = string_for_opt(opts, FALSE)) != 0) {
1497. 			    switch(wintype)  {
1498. 			    	case NHW_MAP:
1499. 					iflags.wc_fontsiz_map = atoi(op);
1500. 					break;
1501. 			    	case NHW_MESSAGE:
1502. 					iflags.wc_fontsiz_message = atoi(op);
1503. 					break;
1504. 			    	case NHW_TEXT:
1505. 					iflags.wc_fontsiz_text = atoi(op);
1506. 					break;
1507. 			    	case NHW_MENU:
1508. 					iflags.wc_fontsiz_menu = atoi(op);
1509. 					break;
1510. 			    	case NHW_STATUS:
1511. 					iflags.wc_fontsiz_status = atoi(op);
1512. 					break;
1513. 			    }
1514. 			}
1515. 			return;
1516. 		} else {
1517. 			badoption(opts);
1518. 		}
1519. 		if (wintype > 0 &&
1520. 		    (op = string_for_opt(opts, FALSE)) != 0) {
1521. 			wc_set_font_name(wintype, op);
1522. #ifdef MAC
1523. 			set_font_name (wintype, op);
1524. #endif
1525. 			return;
1526. 		} else if (negated) bad_negation(fullname, TRUE);
1527. 		return;
1528. 	}
1529. #ifdef CHANGE_COLOR
1530. 	if (match_optname(opts, "palette", 3, TRUE)
1531. # ifdef MAC
1532. 	    || match_optname(opts, "hicolor", 3, TRUE)
1533. # endif
1534. 							) {
1535. 	    int color_number, color_incr;
1536. 
1537. # ifdef MAC
1538. 	    if (match_optname(opts, "hicolor", 3, TRUE)) {
1539. 		if (negated) {
1540. 		    bad_negation("hicolor", FALSE);
1541. 		    return;
1542. 		}
1543. 		color_number = CLR_MAX + 4;	/* HARDCODED inverse number */
1544. 		color_incr = -1;
1545. 	    } else {
1546. # endif
1547. 		if (negated) {
1548. 		    bad_negation("palette", FALSE);
1549. 		    return;
1550. 		}
1551. 		color_number = 0;
1552. 		color_incr = 1;
1553. # ifdef MAC
1554. 	    }
1555. # endif
1556. 	    if ((op = string_for_opt(opts, FALSE)) != (char *)0) {
1557. 		char *pt = op;
1558. 		int cnt, tmp, reverse;
1559. 		long rgb;
1560. 
1561. 		while (*pt && color_number >= 0) {
1562. 		    cnt = 3;
1563. 		    rgb = 0L;
1564. 		    if (*pt == '-') {
1565. 			reverse = 1;
1566. 			pt++;
1567. 		    } else {
1568. 			reverse = 0;
1569. 		    }
1570. 		    while (cnt-- > 0) {
1571. 			if (*pt && *pt != '/') {
1572. # ifdef AMIGA
1573. 			    rgb <<= 4;
1574. # else
1575. 			    rgb <<= 8;
1576. # endif
1577. 			    tmp = *(pt++);
1578. 			    if (isalpha(tmp)) {
1579. 				tmp = (tmp + 9) & 0xf;	/* Assumes ASCII... */
1580. 			    } else {
1581. 				tmp &= 0xf;	/* Digits in ASCII too... */
1582. 			    }
1583. # ifndef AMIGA
1584. 			    /* Add an extra so we fill f -> ff and 0 -> 00 */
1585. 			    rgb += tmp << 4;
1586. # endif
1587. 			    rgb += tmp;
1588. 			}
1589. 		    }
1590. 		    if (*pt == '/') {
1591. 			pt++;
1592. 		    }
1593. 		    change_color(color_number, rgb, reverse);
1594. 		    color_number += color_incr;
1595. 		}
1596. 	    }
1597. 	    if (!initial) {
1598. 		need_redraw = TRUE;
1599. 	    }
1600. 	    return;
1601. 	}
1602. #endif /* CHANGE_COLOR */
1603. 
1604. 	if (match_optname(opts, "fruit", 2, TRUE)) {
1605. 		char empty_str = '\0';
1606. 		op = string_for_opt(opts, negated);
1607. 		if (negated) {
1608. 		    if (op) {
1609. 			bad_negation("fruit", TRUE);
1610. 			return;
1611. 		    }
1612. 		    op = &empty_str;
1613. 		    goto goodfruit;
1614. 		}
1615. 		if (!op) return;
1616. 		if (!initial) {
1617. 		    struct fruit *f;
1618. 
1619. 		    num = 0;
1620. 		    for(f=ffruit; f; f=f->nextf) {
1621. 			if (!strcmp(op, f->fname)) goto goodfruit;
1622. 			num++;
1623. 		    }
1624. 		    if (num >= 100) {
1625. 			pline("Doing that so many times isn't very fruitful.");
1626. 			return;
1627. 		    }
1628. 		}
1629. goodfruit:
1630. 		nmcpy(pl_fruit, op, PL_FSIZ);
1631. 	/* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
1632. 		if (!*pl_fruit)
1633. 		    nmcpy(pl_fruit, "slime mold", PL_FSIZ);
1634. 		if (!initial)
1635. 		    (void)fruitadd(pl_fruit);
1636. 		/* If initial, then initoptions is allowed to do it instead
1637. 		 * of here (initoptions always has to do it even if there's
1638. 		 * no fruit option at all.  Also, we don't want people
1639. 		 * setting multiple fruits in their options.)
1640. 		 */
1641. 		return;
1642. 	}
1643. 
1644. 	/* graphics:string */
1645. 	fullname = "graphics";
1646. 	if (match_optname(opts, fullname, 2, TRUE)) {
1647. 		if (negated) bad_negation(fullname, FALSE);
1648. 		else graphics_opts(opts, fullname, MAXPCHARS, 0);
1649. 		return;
1650. 	}
1651. 	fullname = "dungeon";
1652. 	if (match_optname(opts, fullname, 2, TRUE)) {
1653. 		if (negated) bad_negation(fullname, FALSE);
1654. 		else graphics_opts(opts, fullname, MAXDCHARS, 0);
1655. 		return;
1656. 	}
1657. 	fullname = "traps";
1658. 	if (match_optname(opts, fullname, 2, TRUE)) {
1659. 		if (negated) bad_negation(fullname, FALSE);
1660. 		else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS);
1661. 		return;
1662. 	}
1663. 	fullname = "effects";
1664. 	if (match_optname(opts, fullname, 2, TRUE)) {
1665. 		if (negated) bad_negation(fullname, FALSE);
1666. 		else
1667. 		 graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS);
1668. 		return;
1669. 	}
1670. 
1671. 	/* objects:string */
1672. 	fullname = "objects";
1673. 	if (match_optname(opts, fullname, 7, TRUE)) {
1674. 		int length;
1675. 
1676. 		if (negated) {
1677. 		    bad_negation(fullname, FALSE);
1678. 		    return;
1679. 		}
1680. 		if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1681. 			return;
1682. 		escapes(opts, opts);
1683. 
1684. 		/*
1685. 		 * Override the default object class symbols.  The first
1686. 		 * object in the object class is the "random object".  I
1687. 		 * don't want to use 0 as an object class, so the "random
1688. 		 * object" is basically a place holder.
1689. 		 *
1690. 		 * The object class symbols have already been initialized in
1691. 		 * initoptions().
1692. 		 */
1693. 		length = strlen(opts);
1694. 		if (length >= MAXOCLASSES)
1695. 		    length = MAXOCLASSES-1;	/* don't count RANDOM_OBJECT */
1696. 
1697. 		for (i = 0; i < length; i++)
1698. 		    oc_syms[i+1] = (uchar) opts[i];
1699. 		return;
1700. 	}
1701. 
1702. 	/* monsters:string */
1703. 	fullname = "monsters";
1704. 	if (match_optname(opts, fullname, 8, TRUE)) {
1705. 		int length;
1706. 
1707. 		if (negated) {
1708. 		    bad_negation(fullname, FALSE);
1709. 		    return;
1710. 		}
1711. 		if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1712. 			return;
1713. 		escapes(opts, opts);
1714. 
1715. 		/* Override default mon class symbols set in initoptions(). */
1716. 		length = strlen(opts);
1717. 		if (length >= MAXMCLASSES)
1718. 		    length = MAXMCLASSES-1;	/* mon class 0 unused */
1719. 
1720. 		for (i = 0; i < length; i++)
1721. 		    monsyms[i+1] = (uchar) opts[i];
1722. 		return;
1723. 	}
1724. 	fullname = "warnings";
1725. 	if (match_optname(opts, fullname, 5, TRUE)) {
1726. 		if (negated) bad_negation(fullname, FALSE);
1727. 		else warning_opts(opts, fullname);
1728. 		return;
1729. 	}
1730. 	/* boulder:symbol */
1731. 	fullname = "boulder";
1732. 	if (match_optname(opts, fullname, 7, TRUE)) {
1733. 		int clash = 0;
1734. 		if (negated) {
1735. 		    bad_negation(fullname, FALSE);
1736. 		    return;
1737. 		}
1738. /*		if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */
1739. 		if (!(opts = string_for_opt(opts, FALSE)))
1740. 			return;
1741. 		escapes(opts, opts);
1742. 		if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
1743. 			clash = 1;
1744. 		else if (opts[0] >= '1' && opts[0] <= '5')
1745. 			clash = 2;
1746. 		if (clash) {
1747. 			/* symbol chosen matches a used monster or warning
1748. 			   symbol which is not good - reject it*/
1749. 			pline(
1750. 		  "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
1751. 				opts[0], (clash == 1) ? "monster" : "warning");
1752. 		} else {
1753. 			/*
1754. 			 * Override the default boulder symbol.
1755. 			 */
1756. 			iflags.bouldersym = (uchar) opts[0];
1757. 		}
1758. 		if (!initial) need_redraw = TRUE;
1759. 		return;
1760. 	}
1761. 
1762. 	/* name:string */
1763. 	fullname = "name";
1764. 	if (match_optname(opts, fullname, 4, TRUE)) {
1765. 		if (negated) bad_negation(fullname, FALSE);
1766. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1767. #ifdef PROXY_GRAPHICS
1768. 		    /*
1769. 		     * Can't change player name if authentication required.
1770. 		     */
1771. 		    if (!getenv("HACKAUTHENTICATION"))
1772. #endif
1773. 			nmcpy(plname, op, PL_NSIZ);
1774. 		return;
1775. 	}
1776. 
1777. 	/* role:string or character:string */
1778. 	fullname = "role";
1779. 	if (match_optname(opts, fullname, 4, TRUE) ||
1780. 	    match_optname(opts, (fullname = "character"), 4, TRUE)) {
1781. 		if (negated) bad_negation(fullname, FALSE);
1782. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1783. 			if ((flags.initrole = str2role(op)) == ROLE_NONE)
1784. 				badoption(opts);
1785. 			else  /* Backwards compatibility */
1786. 				nmcpy(pl_character, op, PL_NSIZ);
1787. 		}
1788. 		return;
1789. 	}
1790. 
1791. 	/* race:string */
1792. 	fullname = "race";
1793. 	if (match_optname(opts, fullname, 4, TRUE)) {
1794. 		if (negated) bad_negation(fullname, FALSE);
1795. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1796. 			if ((flags.initrace = str2race(op)) == ROLE_NONE)
1797. 				badoption(opts);
1798. 			else /* Backwards compatibility */
1799. 				pl_race = *op;
1800. 		}
1801. 		return;
1802. 	}
1803. 
1804. 	/* gender:string */
1805. 	fullname = "gender";
1806. 	if (match_optname(opts, fullname, 4, TRUE)) {
1807. 		if (negated) bad_negation(fullname, FALSE);
1808. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1809. 			if ((flags.initgend = str2gend(op)) == ROLE_NONE)
1810. 				badoption(opts);
1811. 			else
1812. 				flags.female = flags.initgend;
1813. 		}
1814. 		return;
1815. 	}
1816. 
1817. 	/* altkeyhandler:string */
1818. 	fullname = "altkeyhandler";
1819. 	if (match_optname(opts, fullname, 4, TRUE)) {
1820. 		if (negated) bad_negation(fullname, FALSE);
1821. 		else if ((op = string_for_opt(opts, negated))) {
1822. #ifdef WIN32CON
1823. 		    (void)strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
1824. 		    load_keyboard_handler();
1825. #endif
1826. 		}
1827. 		return;
1828. 	}
1829. 
1830. 	/* WINCAP
1831. 	 * align_status:[left|top|right|bottom] */
1832. 	fullname = "align_status";
1833. 	if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) {
1834. 		op = string_for_opt(opts, negated);
1835. 		if (op && !negated) {
1836. 		    if (!strncmpi (op, "left", sizeof("left")-1))
1837. 			iflags.wc_align_status = ALIGN_LEFT;
1838. 		    else if (!strncmpi (op, "top", sizeof("top")-1))
1839. 			iflags.wc_align_status = ALIGN_TOP;
1840. 		    else if (!strncmpi (op, "right", sizeof("right")-1))
1841. 			iflags.wc_align_status = ALIGN_RIGHT;
1842. 		    else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1843. 			iflags.wc_align_status = ALIGN_BOTTOM;
1844. 		    else
1845. 			badoption(opts);
1846. 		} else if (negated) bad_negation(fullname, TRUE);
1847. 		return;
1848. 	}
1849. 	/* WINCAP
1850. 	 * align_message:[left|top|right|bottom] */
1851. 	fullname = "align_message";
1852. 	if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) {
1853. 		op = string_for_opt(opts, negated);
1854. 		if (op && !negated) {
1855. 		    if (!strncmpi (op, "left", sizeof("left")-1))
1856. 			iflags.wc_align_message = ALIGN_LEFT;
1857. 		    else if (!strncmpi (op, "top", sizeof("top")-1))
1858. 			iflags.wc_align_message = ALIGN_TOP;
1859. 		    else if (!strncmpi (op, "right", sizeof("right")-1))
1860. 			iflags.wc_align_message = ALIGN_RIGHT;
1861. 		    else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1862. 			iflags.wc_align_message = ALIGN_BOTTOM;
1863. 		    else
1864. 			badoption(opts);
1865. 		} else if (negated) bad_negation(fullname, TRUE);
1866. 		return;
1867. 	}
1868. 	/* align:string */
1869. 	fullname = "align";
1870. 	if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) {
1871. 		if (negated) bad_negation(fullname, FALSE);
1872. 		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1873. 			if ((flags.initalign = str2align(op)) == ROLE_NONE)
1874. 				badoption(opts);
1875. 		return;
1876. 	}
1877. 
1878. 	/* the order to list the pack */
1879. 	fullname = "packorder";
1880. 	if (match_optname(opts, fullname, 4, TRUE)) {
1881. 		if (negated) {
1882. 		    bad_negation(fullname, FALSE);
1883. 		    return;
1884. 		} else if (!(op = string_for_opt(opts, FALSE))) return;
1885. 
1886. 		if (!change_inv_order(op))
1887. 			badoption(opts);
1888. 		return;
1889. 	}
1890. 
1891. 	/* maximum burden picked up before prompt (Warren Cheung) */
1892. 	fullname = "pickup_burden";
1893. 	if (match_optname(opts, fullname, 8, TRUE)) {
1894. 		if (negated) {
1895. 			bad_negation(fullname, FALSE);
1896. 			return;
1897. 		} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1898. 		    switch (tolower(*op)) {
1899. 				/* Unencumbered */
1900. 				case 'u':
1901. 					flags.pickup_burden = UNENCUMBERED;
1902. 					break;
1903. 				/* Burdened (slight encumbrance) */
1904. 				case 'b':
1905. 					flags.pickup_burden = SLT_ENCUMBER;
1906. 					break;
1907. 				/* streSsed (moderate encumbrance) */
1908. 				case 's':
1909. 					flags.pickup_burden = MOD_ENCUMBER;
1910. 					break;
1911. 				/* straiNed (heavy encumbrance) */
1912. 				case 'n':
1913. 					flags.pickup_burden = HVY_ENCUMBER;
1914. 					break;
1915. 				/* OverTaxed (extreme encumbrance) */
1916. 				case 'o':
1917. 				case 't':
1918. 					flags.pickup_burden = EXT_ENCUMBER;
1919. 					break;
1920. 				/* overLoaded */
1921. 				case 'l':
1922. 					flags.pickup_burden = OVERLOADED;
1923. 					break;
1924. 				default:
1925. 				badoption(opts);
1926. 		    }
1927. 		}
1928. 		return;
1929. 	}
1930. 
1931. 	/* types of objects to pick up automatically */
1932. 	if (match_optname(opts, "pickup_types", 8, TRUE)) {
1933. 		char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
1934. 		     qbuf[QBUFSZ], abuf[BUFSZ];
1935. 		int oc_sym;
1936. 		boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
1937. 
1938. 		oc_to_str(flags.pickup_types, tbuf);
1939. 		flags.pickup_types[0] = '\0';	/* all */
1940. 		op = string_for_opt(opts, (compat || !initial));
1941. 		if (!op) {
1942. 		    if (compat || negated || initial) {
1943. 			/* for backwards compatibility, "pickup" without a
1944. 			   value is a synonym for autopickup of all types
1945. 			   (and during initialization, we can't prompt yet) */
1946. 			flags.pickup = !negated;
1947. 			return;
1948. 		    }
1949. 		    oc_to_str(flags.inv_order, ocl);
1950. 		    use_menu = TRUE;
1951. 		    if (flags.menu_style == MENU_TRADITIONAL ||
1952. 			    flags.menu_style == MENU_COMBINATION) {
1953. 			use_menu = FALSE;
1954. 			Sprintf(qbuf, "New pickup_types: [%s am] (%s)",
1955. 				ocl, *tbuf ? tbuf : "all");
1956. 			getlin(qbuf, abuf);
1957. 			op = mungspaces(abuf);
1958. 			if (abuf[0] == '\0' || abuf[0] == '\033')
1959. 			    op = tbuf;		/* restore */
1960. 			else if (abuf[0] == 'm')
1961. 			    use_menu = TRUE;
1962. 		    }
1963. 		    if (use_menu) {
1964. 			(void) choose_classes_menu("Auto-Pickup what?", 1,
1965. 						   TRUE, ocl, tbuf);
1966. 			op = tbuf;
1967. 		    }
1968. 		}
1969. 		if (negated) {
1970. 		    bad_negation("pickup_types", TRUE);
1971. 		    return;
1972. 		}
1973. 		while (*op == ' ') op++;
1974. 		if (*op != 'a' && *op != 'A') {
1975. 		    num = 0;
1976. 		    while (*op) {
1977. 			oc_sym = def_char_to_objclass(*op);
1978. 			/* make sure all are valid obj symbols occuring once */
1979. 			if (oc_sym != MAXOCLASSES &&
1980. 			    !index(flags.pickup_types, oc_sym)) {
1981. 			    flags.pickup_types[num] = (char)oc_sym;
1982. 			    flags.pickup_types[++num] = '\0';
1983. 			} else
1984. 			    badopt = TRUE;
1985. 			op++;
1986. 		    }
1987. 		    if (badopt) badoption(opts);
1988. 		}
1989. 		return;
1990. 	}
1991. 	/* WINCAP
1992. 	 * player_selection: dialog | prompts */
1993. 	fullname = "player_selection";
1994. 	if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) {
1995. 		op = string_for_opt(opts, negated);
1996. 		if (op && !negated) {
1997. 		    if (!strncmpi (op, "dialog", sizeof("dialog")-1))
1998. 			iflags.wc_player_selection = VIA_DIALOG;
1999. 		    else if (!strncmpi (op, "prompt", sizeof("prompt")-1))
2000. 			iflags.wc_player_selection = VIA_PROMPTS;
2001. 		    else
2002. 		    	badoption(opts);
2003. 		} else if (negated) bad_negation(fullname, TRUE);
2004. 		return;
2005. 	}
2006. 
2007. 	/* things to disclose at end of game */
2008. 	if (match_optname(opts, "disclose", 7, TRUE)) {
2009. 		/*
2010. 		 * The order that the end_disclore options are stored:
2011. 		 * inventory, attribs, vanquished, genocided, conduct
2012. 		 * There is an array in flags:
2013. 		 *	end_disclose[NUM_DISCLOSURE_OPT];
2014. 		 * with option settings for the each of the following:
2015. 		 * iagvc [see disclosure_options in decl.c]:
2016. 		 * Legal setting values in that array are:
2017. 		 *	DISCLOSE_PROMPT_DEFAULT_YES  ask with default answer yes
2018. 		 *	DISCLOSE_PROMPT_DEFAULT_NO   ask with default answer no
2019. 		 *	DISCLOSE_YES_WITHOUT_PROMPT  always disclose and don't ask
2020. 		 *	DISCLOSE_NO_WITHOUT_PROMPT   never disclose and don't ask
2021. 		 *
2022. 		 * Those setting values can be used in the option
2023. 		 * string as a prefix to get the desired behaviour.
2024. 		 *
2025. 		 * For backward compatibility, no prefix is required,
2026. 		 * and the presence of a i,a,g,v, or c without a prefix
2027. 		 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
2028. 		 */
2029. 		boolean badopt = FALSE;
2030. 		int idx, prefix_val;
2031. 
2032. 		op = string_for_opt(opts, TRUE);
2033. 		if (op && negated) {
2034. 			bad_negation("disclose", TRUE);
2035. 			return;
2036. 		}
2037. 		/* "disclose" without a value means "all with prompting"
2038. 		   and negated means "none without prompting" */
2039. 		if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
2040. 			if (op && !strcmpi(op, "none")) negated = TRUE;
2041. 			for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
2042. 			    flags.end_disclose[num] = negated ?
2043. 						DISCLOSE_NO_WITHOUT_PROMPT :
2044. 						DISCLOSE_PROMPT_DEFAULT_YES;
2045. 			return;
2046. 		}
2047. 
2048. 		num = 0;
2049. 		prefix_val = -1;
2050. 		while (*op && num < sizeof flags.end_disclose - 1) {
2051. 			register char c, *dop;
2052. 			static char valid_settings[] = {
2053. 				DISCLOSE_PROMPT_DEFAULT_YES,
2054. 				DISCLOSE_PROMPT_DEFAULT_NO,
2055. 				DISCLOSE_YES_WITHOUT_PROMPT,
2056. 				DISCLOSE_NO_WITHOUT_PROMPT,
2057. 				'\0'
2058. 			};
2059. 			c = lowc(*op);
2060. 			if (c == 'k') c = 'v';	/* killed -> vanquished */
2061. 			dop = index(disclosure_options, c);
2062. 			if (dop) {
2063. 				idx = dop - disclosure_options;
2064. 				if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
2065. 				    impossible("bad disclosure index %d %c",
2066. 							idx, c);
2067. 				    continue;
2068. 				}
2069. 				if (prefix_val != -1) {
2070. 				    flags.end_disclose[idx] = prefix_val;
2071. 				    prefix_val = -1;
2072. 				} else
2073. 				    flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
2074. 			} else if (index(valid_settings, c)) {
2075. 				prefix_val = c;
2076. 			} else if (c == ' ') {
2077. 				/* do nothing */
2078. 			} else
2079. 				badopt = TRUE;				
2080. 			op++;
2081. 		}
2082. 		if (badopt) badoption(opts);
2083. 		return;
2084. 	}
2085. 
2086. 	/* scores:5t[op] 5a[round] o[wn] */
2087. 	if (match_optname(opts, "scores", 4, TRUE)) {
2088. 	    if (negated) {
2089. 		bad_negation("scores", FALSE);
2090. 		return;
2091. 	    }
2092. 	    if (!(op = string_for_opt(opts, FALSE))) return;
2093. 
2094. 	    while (*op) {
2095. 		int inum = 1;
2096. 
2097. 		if (digit(*op)) {
2098. 		    inum = atoi(op);
2099. 		    while (digit(*op)) op++;
2100. 		} else if (*op == '!') {
2101. 		    negated = !negated;
2102. 		    op++;
2103. 		}
2104. 		while (*op == ' ') op++;
2105. 
2106. 		switch (*op) {
2107. 		 case 't':
2108. 		 case 'T':  flags.end_top = inum;
2109. 			    break;
2110. 		 case 'a':
2111. 		 case 'A':  flags.end_around = inum;
2112. 			    break;
2113. 		 case 'o':
2114. 		 case 'O':  flags.end_own = !negated;
2115. 			    break;
2116. 		 default:   badoption(opts);
2117. 			    return;
2118. 		}
2119. 		while (letter(*++op) || *op == ' ') continue;
2120. 		if (*op == '/') op++;
2121. 	    }
2122. 	    return;
2123. 	}
2124. 
2125. 	fullname = "suppress_alert";
2126. 	if (match_optname(opts, fullname, 4, TRUE)) {
2127. 		op = string_for_opt(opts, negated);
2128. 		if (negated) bad_negation(fullname, FALSE);
2129. 		else if (op) (void) feature_alert_opts(op,fullname);
2130. 		return;
2131. 	}
2132. 	
2133. 	fullname = "tileset";
2134. 	if (match_optname(opts, fullname, 4, TRUE)) {
2135. 		if (negated || (op = string_for_opt(opts, TRUE)) == 0)
2136. 			tileset[0] = '\0';
2137. 		else {
2138. 			/*
2139. 			 * The tileset may not be defined (yet) if we're
2140. 			 * in initial mode, otherwise it must exist.
2141. 			 */
2142. 			if (!initial) {
2143. 				int len = strlen(op);
2144. 				for(i = 0; i < no_tilesets; i++)
2145. 				    if (len == strlen(tilesets[i].name) &&
2146. 				      !strncmpi(tilesets[i].name, op, len))
2147. 					break;
2148. 				if (i == no_tilesets) {
2149. 				    pline("Tileset %s not defined.", op);
2150. 				    return;
2151. 				}
2152. 				else	/* Use canonical case */
2153. 				    strcpy(tileset, tilesets[i].name);
2154. 			}
2155. 			else
2156. 				nmcpy(tileset, op, PL_PSIZ);
2157. 		}
2158. 		if (!initial)
2159. 		    need_redraw = TRUE;
2160. 		return;
2161. 	}
2162. 	
2163. #if defined(VIDEOSHADES) && !defined(NO_TERMS)
2164. 	/* videocolors:string */
2165. 	fullname = "videocolors";
2166. 	if (match_optname(opts, fullname, 6, TRUE) ||
2167. 	    match_optname(opts, "videocolours", 10, TRUE)) {
2168. 		if (negated) {
2169. 			bad_negation(fullname, FALSE);
2170. 			return;
2171. 		}
2172. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2173. 			return;
2174. 		}
2175. 		if (!assign_videocolors(opts))
2176. 			badoption(opts);
2177. 		return;
2178. 	}
2179. # ifdef MSDOS
2180. 	/* videoshades:string */
2181. 	fullname = "videoshades";
2182. 	if (match_optname(opts, fullname, 6, TRUE)) {
2183. 		if (negated) {
2184. 			bad_negation(fullname, FALSE);
2185. 			return;
2186. 		}
2187. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2188. 			return;
2189. 		}
2190. 		if (!assign_videoshades(opts))
2191. 			badoption(opts);
2192. 		return;
2193. 	}
2194. # endif
2195. #endif /* VIDEOSHADES */
2196. #ifdef MSDOS
2197. # ifdef NO_TERMS
2198. 	/* video:string -- must be after longer tests */
2199. 	fullname = "video";
2200. 	if (match_optname(opts, fullname, 5, TRUE)) {
2201. 		if (negated) {
2202. 			bad_negation(fullname, FALSE);
2203. 			return;
2204. 		}
2205. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2206. 			return;
2207. 		}
2208. 		if (!assign_video(opts))
2209. 			badoption(opts);
2210. 		return;
2211. 	}
2212. # endif /* NO_TERMS */
2213. 	/* soundcard:string -- careful not to match boolean 'sound' */
2214. 	fullname = "soundcard";
2215. 	if (match_optname(opts, fullname, 6, TRUE)) {
2216. 		if (negated) {
2217. 			bad_negation(fullname, FALSE);
2218. 			return;
2219. 		}
2220. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2221. 			return;
2222. 		}
2223. 		if (!assign_soundcard(opts))
2224. 			badoption(opts);
2225. 		return;
2226. 	}
2227. #endif /* MSDOS */
2228. 
2229. 	/* WINCAP
2230. 	 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12|
2231. 			ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */
2232. 	fullname = "map_mode";
2233. 	if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) {
2234. 		op = string_for_opt(opts, negated);
2235. 		if (op && !negated) {
2236. 		    if (!strncmpi (op, "tiles", sizeof("tiles")-1))
2237. 			iflags.wc_map_mode = MAP_MODE_TILES;
2238. 		    else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1))
2239. 			iflags.wc_map_mode = MAP_MODE_ASCII4x6;
2240. 		    else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1))
2241. 			iflags.wc_map_mode = MAP_MODE_ASCII6x8;
2242. 		    else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1))
2243. 			iflags.wc_map_mode = MAP_MODE_ASCII8x8;
2244. 		    else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1))
2245. 			iflags.wc_map_mode = MAP_MODE_ASCII16x8;
2246. 		    else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1))
2247. 			iflags.wc_map_mode = MAP_MODE_ASCII7x12;
2248. 		    else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1))
2249. 			iflags.wc_map_mode = MAP_MODE_ASCII8x12;
2250. 		    else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1))
2251. 			iflags.wc_map_mode = MAP_MODE_ASCII16x12;
2252. 		    else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1))
2253. 			iflags.wc_map_mode = MAP_MODE_ASCII12x16;
2254. 		    else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1))
2255. 			iflags.wc_map_mode = MAP_MODE_ASCII10x18;
2256. 		    else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1))
2257. 			iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
2258. 		    else
2259. 		    	badoption(opts);
2260. 		} else if (negated) bad_negation(fullname, TRUE);
2261. 		return;
2262. 	}
2263. 	/* WINCAP
2264. 	 * scroll_amount:nn */
2265. 	fullname = "scroll_amount";
2266. 	if (match_optname(opts, fullname, sizeof("scroll_amount")-1, TRUE)) {
2267. 		op = string_for_opt(opts, negated);
2268. 		if ((negated && !op) || (!negated && op)) {
2269. 			iflags.wc_scroll_amount = negated ? 1 : atoi(op);
2270. 		} else if (negated) bad_negation(fullname, TRUE);
2271. 		return;
2272. 	}
2273. 	/* WINCAP
2274. 	 * scroll_margin:nn */
2275. 	fullname = "scroll_margin";
2276. 	if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) {
2277. 		op = string_for_opt(opts, negated);
2278. 		if ((negated && !op) || (!negated && op)) {
2279. 			iflags.wc_scroll_margin = negated ? 5 : atoi(op);
2280. 		} else if (negated) bad_negation(fullname, TRUE);
2281. 		return;
2282. 	}
2283. 	fullname = "subkeyvalue";
2284. 	if (match_optname(opts, fullname, 5, TRUE)) {
2285. 		if (negated) bad_negation(fullname, FALSE);
2286. 		else {
2287. #if defined(WIN32CON)
2288. 			op = string_for_opt(opts, 0);
2289. 			map_subkeyvalue(op);
2290. #endif
2291. 		}
2292. 		return;
2293. 	}
2294. 	/* WINCAP
2295. 	 * tile_width:nn */
2296. 	fullname = "tile_width";
2297. 	if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) {
2298. 		op = string_for_opt(opts, negated);
2299. 		if ((negated && !op) || (!negated && op)) {
2300. 			iflags.wc_tile_width = negated ? 0 : atoi(op);
2301. 		} else if (negated) bad_negation(fullname, TRUE);
2302. 		return;
2303. 	}
2304. 	/* WINCAP
2305. 	 * tile_file:name */
2306. 	fullname = "tile_file";
2307. 	if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) {
2308. 		if ((op = string_for_opt(opts, FALSE)) != 0) {
2309. 			if (iflags.wc_tile_file) free(iflags.wc_tile_file);
2310. 			iflags.wc_tile_file = (char *)alloc(strlen(op) + 1);
2311. 			Strcpy(iflags.wc_tile_file, op);
2312. 		}
2313. 		return;
2314. 	}
2315. 	/* WINCAP
2316. 	 * tile_height:nn */
2317. 	fullname = "tile_height";
2318. 	if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) {
2319. 		op = string_for_opt(opts, negated);
2320. 		if ((negated && !op) || (!negated && op)) {
2321. 			iflags.wc_tile_height = negated ? 0 : atoi(op);
2322. 		} else if (negated) bad_negation(fullname, TRUE);
2323. 		return;
2324. 	}
2325. 	/* WINCAP
2326. 	 * vary_msgcount:nn */
2327. 	fullname = "vary_msgcount";
2328. 	if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) {
2329. 		op = string_for_opt(opts, negated);
2330. 		if ((negated && !op) || (!negated && op)) {
2331. 			iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
2332. 		} else if (negated) bad_negation(fullname, TRUE);
2333. 		return;
2334. 	}
2335. 	fullname = "windowtype";
2336. 	if (match_optname(opts, fullname, 3, TRUE)) {
2337. 	    if (negated) {
2338. 		bad_negation(fullname, FALSE);
2339. 		return;
2340. 	    } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2341. 		char buf[WINTYPELEN];
2342. 		nmcpy(buf, op, WINTYPELEN);
2343. 		choose_windows(buf);
2344. 	    }
2345. 	    return;
2346. 	}
2347. 
2348. 	/* WINCAP
2349. 	 * setting window colors
2350.          * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
2351.          */
2352. 	fullname = "windowcolors";
2353. 	if (match_optname(opts, fullname, 7, TRUE)) {
2354. 		if ((op = string_for_opt(opts, FALSE)) != 0) {
2355. 			if (!wc_set_window_colors(op))
2356. 				badoption(opts);
2357. 		} else if (negated) bad_negation(fullname, TRUE);
2358. 		return;
2359. 	}
2360. 
2361. 	/* menustyle:traditional or combo or full or partial */
2362. 	if (match_optname(opts, "menustyle", 4, TRUE)) {
2363. 		int tmp;
2364. 		boolean val_required = (strlen(opts) > 5 && !negated);
2365. 
2366. 		if (!(op = string_for_opt(opts, !val_required))) {
2367. 		    if (val_required) return; /* string_for_opt gave feedback */
2368. 		    tmp = negated ? 'n' : 'f';
2369. 		} else {
2370. 		    tmp = tolower(*op);
2371. 		}
2372. 		switch (tmp) {
2373. 			case 'n':	/* none */
2374. 			case 't':	/* traditional */
2375. 				flags.menu_style = MENU_TRADITIONAL;
2376. 				break;
2377. 			case 'c':	/* combo: trad.class sel+menu */
2378. 				flags.menu_style = MENU_COMBINATION;
2379. 				break;
2380. 			case 'p':	/* partial: no class menu */
2381. 				flags.menu_style = MENU_PARTIAL;
2382. 				break;
2383. 			case 'f':	/* full: class menu + menu */
2384. 				flags.menu_style = MENU_FULL;
2385. 				break;
2386. 			default:
2387. 				badoption(opts);
2388. 		}
2389. 		return;
2390. 	}
2391. 
2392. 	fullname = "menu_headings";
2393. 	if (match_optname(opts, fullname, 12, TRUE)) {
2394. 		if (negated) {
2395. 			bad_negation(fullname, FALSE);
2396. 			return;
2397. 		}
2398. 		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2399. 			return;
2400. 		}
2401. 		if (!strcmpi(opts,"bold"))
2402. 			iflags.menu_headings = ATR_BOLD;
2403. 		else if (!strcmpi(opts,"inverse"))
2404. 			iflags.menu_headings = ATR_INVERSE;
2405. 		else if (!strcmpi(opts,"underline"))
2406. 			iflags.menu_headings = ATR_ULINE;
2407. 		else
2408. 			badoption(opts);
2409. 		return;
2410. 	}
2411. 
2412. 	/* check for menu command mapping */
2413. 	for (i = 0; i < NUM_MENU_CMDS; i++) {
2414. 	    fullname = default_menu_cmd_info[i].name;
2415. 	    if (match_optname(opts, fullname, (int)strlen(fullname), TRUE)) {
2416. 		if (negated)
2417. 		    bad_negation(fullname, FALSE);
2418. 		else if ((op = string_for_opt(opts, FALSE)) != 0) {
2419. 		    int j;
2420. 		    char c, op_buf[BUFSZ];
2421. 		    boolean isbad = FALSE;
2422. 
2423. 		    escapes(op, op_buf);
2424. 		    c = *op_buf;
2425. 
2426. 		    if (c == 0 || c == '\r' || c == '\n' || c == '\033' ||
2427. 			    c == ' ' || digit(c) || (letter(c) && c != '@'))
2428. 			isbad = TRUE;
2429. 		    else	/* reject default object class symbols */
2430. 			for (j = 1; j < MAXOCLASSES; j++)
2431. 			    if (c == def_oc_syms[i]) {
2432. 				isbad = TRUE;
2433. 				break;
2434. 			    }
2435. 
2436. 		    if (isbad)
2437. 			badoption(opts);
2438. 		    else
2439. 			add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
2440. 		}
2441. 		return;
2442. 	    }
2443. 	}
2444. 
2445. 	/* OK, if we still haven't recognized the option, check the boolean
2446. 	 * options list
2447. 	 */
2448. 	for (i = 0; boolopt[i].name; i++) {
2449. 		if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
2450. 			/* options that don't exist */
2451. 			if (!boolopt[i].addr) {
2452. 			    if (!initial && !negated)
2453. 				pline_The("\"%s\" option is not available.",
2454. 					boolopt[i].name);
2455. 			    return;
2456. 			}
2457. 			/* options that must come from config file */
2458. 			if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
2459. 			    rejectoption(boolopt[i].name);
2460. 			    return;
2461. 			}
2462. 
2463. 			*(boolopt[i].addr) = !negated;
2464. 
2465. 			duplicate_opt_detection(boolopt[i].name, 0);
2466. 
2467. #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV)
2468. 			if (FALSE
2469. # ifdef TERMLIB
2470. 				 || (boolopt[i].addr) == &iflags.DECgraphics
2471. # endif
2472. # ifdef ASCIIGRAPH
2473. 				 || (boolopt[i].addr) == &iflags.IBMgraphics
2474. # endif
2475. # ifdef MAC_GRAPHICS_ENV
2476. 				 || (boolopt[i].addr) == &iflags.MACgraphics
2477. # endif
2478. 				) {
2479. # ifdef REINCARNATION
2480. 			    /* [ALI] GTK port may call doset() after initial
2481. 			     * but before we start a game. Prevent false match.
2482. 			     */
2483. 			    if (!initial && u.uz.dlevel &&
2484. 			      Is_rogue_level(&u.uz))
2485. 				assign_rogue_graphics(FALSE);
2486. # endif
2487. 			    need_redraw = TRUE;
2488. # ifdef TERMLIB
2489. 			    if ((boolopt[i].addr) == &iflags.DECgraphics)
2490. 				switch_graphics(iflags.DECgraphics ?
2491. 						DEC_GRAPHICS : ASCII_GRAPHICS);
2492. # endif
2493. # ifdef ASCIIGRAPH
2494. 			    if ((boolopt[i].addr) == &iflags.IBMgraphics)
2495. 				switch_graphics(iflags.IBMgraphics ?
2496. 						IBM_GRAPHICS : ASCII_GRAPHICS);
2497. # endif
2498. # ifdef MAC_GRAPHICS_ENV
2499. 			    if ((boolopt[i].addr) == &iflags.MACgraphics)
2500. 				switch_graphics(iflags.MACgraphics ?
2501. 						MAC_GRAPHICS : ASCII_GRAPHICS);
2502. # endif
2503. # ifdef REINCARNATION
2504. 			    if (!initial && u.uz.dlevel &&
2505. 			      Is_rogue_level(&u.uz))
2506. 				assign_rogue_graphics(TRUE);
2507. # endif
2508. 			}
2509. #endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */
2510. 
2511. 			/* only do processing below if setting with doset() */
2512. 			if (initial) return;
2513. 
2514. 			if ((boolopt[i].addr) == &flags.time
2515. #ifdef EXP_ON_BOTL
2516. 			 || (boolopt[i].addr) == &flags.showexp
2517. #endif
2518. #ifdef SCORE_ON_BOTL
2519. 			 || (boolopt[i].addr) == &flags.showscore
2520. #endif
2521. #ifdef SHOW_WEIGHT
2522. 			 || (boolopt[i].addr) == &flags.showweight
2523. #endif
2524. 			    )
2525. 			    bot_reconfig();
2526. 
2527. 			else if ((boolopt[i].addr) == &flags.invlet_constant) {
2528. 			    if (flags.invlet_constant) reassign();
2529. 			}
2530. #ifdef LAN_MAIL
2531. 			else if ((boolopt[i].addr) == &flags.biff) {
2532. 			    if (flags.biff) lan_mail_init();
2533. 			    else lan_mail_finish();
2534. 			}
2535. #endif
2536. 			else if ((boolopt[i].addr) == &flags.lit_corridor) {
2537. 			    /*
2538. 			     * All corridor squares seen via night vision or
2539. 			     * candles & lamps change.  Update them by calling
2540. 			     * newsym() on them.  Don't do this if we are
2541. 			     * initializing the options --- the vision system
2542. 			     * isn't set up yet.
2543. 			     */
2544. 			    if (u.uz.dlevel)
2545. 			    {
2546. 			    vision_recalc(2);		/* shut down vision */
2547. 			    vision_full_recalc = 1;	/* delayed recalc */
2548. 			}
2549. 			}
2550. 			else if ((boolopt[i].addr) == &iflags.use_inverse ||
2551. 					(boolopt[i].addr) == &iflags.showrace ||
2552. 					(boolopt[i].addr) == &iflags.hilite_pet) {
2553. 			    need_redraw = TRUE;
2554. 			}
2555. #ifdef TEXTCOLOR
2556. 			else if ((boolopt[i].addr) == &iflags.use_color) {
2557. 			    need_redraw = TRUE;
2558. # ifdef TOS
2559. 			    if ((boolopt[i].addr) == &iflags.use_color
2560. 				&& iflags.BIOS) {
2561. 				if (colors_changed)
2562. 				    restore_colors();
2563. 				else
2564. 				    set_colors();
2565. 			    }
2566. # endif
2567. 			}
2568. #endif
2569.                         else if ((boolopt[i].addr) == &flags.perm_invent)
2570.                             update_inventory();
2571. 
2572. 			return;
2573. 		}
2574. 	}
2575. 
2576. 	/* out of valid options */
2577. 	badoption(opts);
2578. }
2579. 
2580. static void
2581. parseauthopt(opts)
2582. register char *opts;
2583. {
2584. 	register char *op;
2585. 	boolean negated;
2586. 	const char *fullname;
2587. 
2588. 	if (strlen(opts) > BUFSZ/2) {
2589. 		badauthoption("option too long");
2590. 		return;
2591. 	}
2592. 
2593. 	/* strip leading and trailing white space */
2594. 	while (isspace((int)*opts)) opts++;
2595. 	op = eos(opts);
2596. 	while (--op >= opts && isspace((int)*op)) *op = '\0';
2597. 
2598. 	if (!*opts) return;
2599. 	negated = FALSE;
2600. 	while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
2601. 		if (*opts == '!') opts++; else opts += 2;
2602. 		negated = !negated;
2603. 	}
2604. 
2605. 	/* compound options */
2606. 
2607.         fullname = "prog";
2608. 	if (match_optname(opts, fullname, 4, TRUE)) {
2609. 		if (negated) bad_negation(fullname, FALSE);
2610. 		else if ((op = string_for_auth_opt(opts, FALSE)) != 0)
2611.                         nmcpy(authentication.prog, op, BUFSZ);
2612. 		return;
2613. 	}
2614. 
2615.         fullname = "args";
2616. 	if (match_optname(opts, fullname, 4, TRUE)) {
2617. 		if (negated) bad_negation(fullname, FALSE);
2618. 		else if ((op = string_for_auth_opt(opts, FALSE)) != 0)
2619.                         nmcpy(authentication.args, op, BUFSZ);
2620. 		return;
2621. 	}
2622. 
2623. 	/* out of valid options */
2624. 	badauthoption(opts);
2625. }
2626. 
2627. void
2628. parseauthentication(opts)
2629. register char *opts;
2630. {
2631. 	register char *op;
2632. 
2633. 	/* Initial values */
2634. 	authentication.prog[0] = '\0';
2635. 	authentication.args[0] = '\0';
2636. 
2637. 	while ((op = index(opts, ',')) != 0) {
2638. 		*op++ = 0;
2639. 		parseauthopt(opts);
2640. 		opts = op;
2641. 	}
2642. 	parseauthopt(opts);
2643. 
2644. 	if (!authentication.prog[0] && authentication.args[0])
2645. 		badauthoption("Arguments given but no program specified.");
2646. }
2647. 
2648. static void
2649. parsetilesetopt(opts)
2650. register char *opts;
2651. {
2652. 	register char *op;
2653. 	boolean negated;
2654. 	int i;
2655. 	const char *fullname;
2656. 
2657. 	if (strlen(opts) > BUFSZ/2) {
2658. 		badtileoption("option too long");
2659. 		return;
2660. 	}
2661. 
2662. 	/* strip leading and trailing white space */
2663. 	while (isspace((int)*opts)) opts++;
2664. 	op = eos(opts);
2665. 	while (--op >= opts && isspace((int)*op)) *op = '\0';
2666. 
2667. 	if (!*opts) return;
2668. 	negated = FALSE;
2669. 	while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
2670. 		if (*opts == '!') opts++; else opts += 2;
2671. 		negated = !negated;
2672. 	}
2673. 
2674. 	/* compound options */
2675. 
2676.         fullname = "name";
2677. 	if (match_optname(opts, fullname, 4, TRUE)) {
2678. 		if (negated) bad_negation(fullname, FALSE);
2679. 		else if ((op = string_for_tile_opt(opts, FALSE)) != 0)
2680.                         nmcpy(tilesets[no_tilesets].name, op, PL_PSIZ);
2681. 		return;
2682. 	}
2683. 
2684.         fullname = "filename";
2685. 	if (match_optname(opts, fullname, 4, TRUE)) {
2686. 		if (negated) bad_negation(fullname, FALSE);
2687. 		else if ((op = string_for_tile_opt(opts, FALSE)) != 0)
2688.                         nmcpy(tilesets[no_tilesets].file, op,
2689. 			  TILESET_MAX_FILENAME);
2690. 		return;
2691. 	}
2692. 
2693. 	/* OK, if we still haven't recognized the option, check the boolean
2694. 	 * options list
2695. 	 */
2696. 	for (i = 0; booltileopt[i].name; i++) {
2697. 		if (match_optname(opts, booltileopt[i].name, 3, FALSE)) {
2698. 			if (negated)
2699. 			    tilesets[no_tilesets].flags &= ~booltileopt[i].flag;
2700. 			else
2701. 			    tilesets[no_tilesets].flags |= booltileopt[i].flag;
2702. 			return;
2703. 		}
2704. 	}
2705. 
2706. 	/* out of valid options */
2707. 	badtileoption(opts);
2708. }
2709. 
2710. void
2711. parsetileset(opts)
2712. register char *opts;
2713. {
2714. 	register char *op;
2715. 	int i;
2716. 
2717. 	if (no_tilesets >= MAXNOTILESETS) {
2718. 		badtileoption("too many tilesets");
2719. 		return;
2720. 	}
2721. 
2722. 	/* Initial values */
2723. 	tilesets[no_tilesets].name[0] = '\0';
2724. 	tilesets[no_tilesets].file[0] = '\0';
2725. 	tilesets[no_tilesets].flags = 0;
2726. 	for (i = 0; booltileopt[i].name; i++)
2727. 		tilesets[no_tilesets].flags |= booltileopt[i].initvalue;
2728. 
2729. 	while ((op = index(opts, ',')) != 0) {
2730. 		*op++ = 0;
2731. 		parsetilesetopt(opts);
2732. 		opts = op;
2733. 	}
2734. 	parsetilesetopt(opts);
2735. 
2736. 	if (tilesets[no_tilesets].name[0] == '\0' ||
2737. 	  tilesets[no_tilesets].file[0] == '\0') {
2738. 		badtileoption("Incomplete tileset definition.");
2739. 	}
2740. 	else
2741. 		no_tilesets++;
2742. }
2743. 
2744. 
2745. static NEARDATA const char *menutype[] = {
2746. 	"traditional", "combination", "partial", "full"
2747. };
2748. 
2749. static NEARDATA const char *burdentype[] = {
2750. 	"unencumbered", "burdened", "stressed",
2751. 	"strained", "overtaxed", "overloaded"
2752. };
2753. 
2754. static NEARDATA const char *runmodes[] = {
2755. 	"teleport", "run", "walk", "crawl"
2756. };
2757. 
2758. /*
2759.  * Convert the given string of object classes to a string of default object
2760.  * symbols.
2761.  */
2762. STATIC_OVL void
2763. oc_to_str(src,dest)
2764.     char *src, *dest;
2765. {
2766.     int i;
2767. 
2768.     while ((i = (int) *src++) != 0) {
2769. 	if (i < 0 || i >= MAXOCLASSES)
2770. 	    impossible("oc_to_str:  illegal object class %d", i);
2771. 	else
2772. 	    *dest++ = def_oc_syms[i];
2773.     }
2774.     *dest = '\0';
2775. }
2776. 
2777. /*
2778.  * Add the given mapping to the menu command map list.  Always keep the
2779.  * maps valid C strings.
2780.  */
2781. void
2782. add_menu_cmd_alias(from_ch, to_ch)
2783.     char from_ch, to_ch;
2784. {
2785.     if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS)
2786. 	pline("out of menu map space.");
2787.     else {
2788. 	mapped_menu_cmds[n_menu_mapped] = from_ch;
2789. 	mapped_menu_op[n_menu_mapped] = to_ch;
2790. 	n_menu_mapped++;
2791. 	mapped_menu_cmds[n_menu_mapped] = 0;
2792. 	mapped_menu_op[n_menu_mapped] = 0;
2793.     }
2794. }
2795. 
2796. /*
2797.  * Map the given character to its corresponding menu command.  If it
2798.  * doesn't match anything, just return the original.
2799.  */
2800. char
2801. map_menu_cmd(ch)
2802.     char ch;
2803. {
2804.     char *found = index(mapped_menu_cmds, ch);
2805.     if (found) {
2806. 	int idx = found - mapped_menu_cmds;
2807. 	ch = mapped_menu_op[idx];
2808.     }
2809.     return ch;
2810. }
2811. 
2812. 
2813. #if defined(MICRO) || defined(MAC) || defined(WIN32)
2814. # define OPTIONS_HEADING "OPTIONS"
2815. #else
2816. # define OPTIONS_HEADING NETHACK_ENV_OPTIONS
2817. #endif
2818. 
2819. static char fmtstr_doset_add_menu[] = "%s%-15s [%s]   "; 
2820. static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
2821. 
2822. STATIC_OVL void
2823. doset_add_menu(win, option, indexoffset)
2824.     winid win;			/* window to add to */
2825.     const char *option;		/* option name */
2826.     int indexoffset;		/* value to add to index in compopt[], or zero
2827. 				   if option cannot be changed */
2828. {
2829.     const char *value = "unknown";		/* current value */
2830.     char buf[BUFSZ], buf2[BUFSZ];
2831.     anything any;
2832.     int i;
2833. 
2834.     any.a_void = 0;
2835.     if (indexoffset == 0) {
2836. 	any.a_int = 0;
2837. 	value = get_compopt_value(option, buf2);
2838.     } else {
2839. 	for (i=0; compopt[i].name; i++)
2840. 	    if (strcmp(option, compopt[i].name) == 0) break;
2841. 
2842. 	if (compopt[i].name) {
2843. 	    any.a_int = i + 1 + indexoffset;
2844. 	    value = get_compopt_value(option, buf2);
2845. 	} else {
2846. 	    /* We are trying to add an option not found in compopt[].
2847. 	       This is almost certainly bad, but we'll let it through anyway
2848. 	       (with a zero value, so it can't be selected). */
2849. 	    any.a_int = 0;
2850. 	}
2851.     }
2852.     /* "    " replaces "a - " -- assumes menus follow that style */
2853.     if (!iflags.menu_tab_sep)
2854. 	Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ", option, value);
2855.     else
2856. 	Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
2857.     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
2858. }
2859. 
2860. /* Changing options via menu by Per Liboriussen */
2861. int
2862. doset()
2863. {
2864. 	char buf[BUFSZ], buf2[BUFSZ];
2865. 	int i, pass, boolcount, pick_cnt, pick_idx, opt_indx;
2866. 	boolean *bool_p;
2867. 	winid tmpwin;
2868. 	anything any;
2869. 	menu_item *pick_list;
2870. 	int indexoffset, startpass, endpass;
2871. 	boolean setinitial = FALSE, fromfile = FALSE;
2872. 	int biggest_name = 0;
2873. 
2874. 	tmpwin = create_nhwindow(NHW_MENU);
2875. 	start_menu(tmpwin);
2876. 
2877. 	any.a_void = 0;
2878.  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2879. 		 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
2880. 	any.a_int = 0;
2881. 	/* first list any other non-modifiable booleans, then modifiable ones */
2882. 	for (pass = 0; pass <= 1; pass++)
2883. 	    for (i = 0; boolopt[i].name; i++)
2884. 		if ((bool_p = boolopt[i].addr) != 0 &&
2885. 			((boolopt[i].optflags == DISP_IN_GAME && pass == 0) ||
2886. 			 (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
2887. 		    if (bool_p == &flags.female) continue;  /* obsolete */
2888. #ifdef WIZARD
2889. #ifndef OBJ_SANITY
2890. 		    if (bool_p == &iflags.sanity_check && !wizard) continue;
2891. #endif
2892. 		    if (bool_p == &iflags.menu_tab_sep && !wizard) continue;
2893. #endif
2894. 		    if (is_wc_option(boolopt[i].name) &&
2895. 			!wc_supported(boolopt[i].name)) continue;
2896. 		    if (is_wc2_option(boolopt[i].name) &&
2897. 			!wc2_supported(boolopt[i].name)) continue;
2898. 		    any.a_int = (pass == 0) ? 0 : i + 1;
2899. 		    if (!iflags.menu_tab_sep)
2900. 			Sprintf(buf, "%s%-13s [%s]",
2901. 			    pass == 0 ? "    " : "",
2902. 			    boolopt[i].name, *bool_p ? "true" : "false");
2903.  		    else
2904. 			Sprintf(buf, "%s\t[%s]",
2905. 			    boolopt[i].name, *bool_p ? "true" : "false");
2906. 		    add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
2907. 			     ATR_NONE, buf, MENU_UNSELECTED);
2908. 		}
2909. 
2910. 	boolcount = i;
2911. 	indexoffset = boolcount;
2912. 	any.a_void = 0;
2913. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2914.  add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2915. 		 "Compounds (selecting will prompt for new value):",
2916. 		 MENU_UNSELECTED);
2917. 
2918. 	startpass = DISP_IN_GAME;
2919. 	endpass = SET_IN_GAME;
2920. 
2921. 	/* spin through the options to find the biggest name
2922.            and adjust the format string accordingly if needed */
2923. 	biggest_name = 0;
2924. 	for (i = 0; compopt[i].name; i++)
2925. 		if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass &&
2926. 		    strlen(compopt[i].name) > (unsigned) biggest_name)
2927. 			biggest_name = (int) strlen(compopt[i].name);
2928. 	if (biggest_name > 30) biggest_name = 30;
2929. 	if (!iflags.menu_tab_sep)
2930. 		Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
2931. 	
2932. 	/* deliberately put `name', `role', `race', `gender' first */
2933. 	doset_add_menu(tmpwin, "name", 0);
2934. 	doset_add_menu(tmpwin, "role", 0);
2935. 	doset_add_menu(tmpwin, "race", 0);
2936. 	doset_add_menu(tmpwin, "gender", 0);
2937. 
2938. 	for (pass = startpass; pass <= endpass; pass++) 
2939. 	    for (i = 0; compopt[i].name; i++)
2940. 		if (compopt[i].optflags == pass) {
2941.  		    	if (!strcmp(compopt[i].name, "name") ||
2942. 		    	    !strcmp(compopt[i].name, "role") ||
2943. 		    	    !strcmp(compopt[i].name, "race") ||
2944. 		    	    !strcmp(compopt[i].name, "gender"))
2945. 		    	    	continue;
2946. 		    	else if (is_wc_option(compopt[i].name) &&
2947. 					!wc_supported(compopt[i].name))
2948. 		    		continue;
2949. 		    	else if (is_wc2_option(compopt[i].name) &&
2950. 					!wc2_supported(compopt[i].name))
2951. 		    		continue;
2952. 		    	else
2953. 				doset_add_menu(tmpwin, compopt[i].name,
2954. 					(pass == DISP_IN_GAME) ? 0 : indexoffset);
2955. 		}
2956. #ifdef AUTOPICKUP_EXCEPTIONS
2957. 	any.a_int = -1;
2958. 	Sprintf(buf, "autopickup exceptions (%d currently set)",
2959. 		count_ape_maps((int *)0, (int *)0));
2960. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
2961. 
2962. #endif /* AUTOPICKUP_EXCEPTIONS */
2963. #ifdef PREFIXES_IN_USE
2964. 	any.a_void = 0;
2965. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2966. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2967. 		 "Variable playground locations:", MENU_UNSELECTED);
2968. 	for (i = 0; i < PREFIX_COUNT; i++)
2969. 		doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
2970. #endif
2971. 	end_menu(tmpwin, "Set what options?");
2972. 	need_redraw = FALSE;
2973. 	if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
2974. 	    /*
2975. 	     * Walk down the selection list and either invert the booleans
2976. 	     * or prompt for new values. In most cases, call parseoptions()
2977. 	     * to take care of options that require special attention, like
2978. 	     * redraws.
2979. 	     */
2980. 	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2981. 		opt_indx = pick_list[pick_idx].item.a_int - 1;
2982. #ifdef AUTOPICKUP_EXCEPTIONS
2983. 		if (opt_indx == -2) {
2984. 		    special_handling("autopickup_exception",
2985. 		    			setinitial, fromfile);
2986. 		} else
2987. #endif
2988. 		if (opt_indx < boolcount) {
2989. 		    /* boolean option */
2990. 		    Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
2991. 			    boolopt[opt_indx].name);
2992. 		    parseoptions(buf, setinitial, fromfile);
2993. 		    if (wc_supported(boolopt[opt_indx].name) ||
2994. 		    	wc2_supported(boolopt[opt_indx].name))
2995. 			preference_update(boolopt[opt_indx].name);
2996. 		} else {
2997. 		    /* compound option */
2998. 		    opt_indx -= boolcount;
2999. 
3000. 		    if (!special_handling(compopt[opt_indx].name,
3001. 							setinitial, fromfile)) {
3002. 			Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
3003. 			getlin(buf, buf2);
3004. 			if (buf2[0] == '\033')
3005. 			    continue;
3006. 			Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
3007. 			/* pass the buck */
3008. 			parseoptions(buf, setinitial, fromfile);
3009. 		    }
3010. 		    if (wc_supported(compopt[opt_indx].name) ||
3011. 			wc2_supported(compopt[opt_indx].name))
3012. 			preference_update(compopt[opt_indx].name);
3013. 		}
3014. 	    }
3015. 	    free((genericptr_t)pick_list);
3016. 	    pick_list = (menu_item *)0;
3017. 	}
3018. 
3019. 	destroy_nhwindow(tmpwin);
3020. 	if (need_redraw)
3021. 	    (void) doredraw();
3022. 	return 0;
3023. }
3024. 
3025. STATIC_OVL boolean
3026. special_handling(optname, setinitial, setfromfile)
3027. const char *optname;
3028. boolean setinitial,setfromfile;
3029. {
3030.     winid tmpwin;
3031.     anything any;
3032.     int i;
3033.     char buf[BUFSZ];
3034.     boolean retval = FALSE;
3035.     
3036.     /* Special handling of menustyle, pickup_burden, pickup_types,
3037.      * disclose, runmode, msg_window, menu_headings, and number_pad options.
3038. #ifdef AUTOPICKUP_EXCEPTIONS
3039.      * Also takes care of interactive autopickup_exception_handling changes.
3040. #endif
3041.      */
3042.     if (!strcmp("menustyle", optname)) {
3043. 	const char *style_name;
3044. 	menu_item *style_pick = (menu_item *)0;
3045.         tmpwin = create_nhwindow(NHW_MENU);
3046. 	start_menu(tmpwin);
3047. 	for (i = 0; i < SIZE(menutype); i++) {
3048. 		style_name = menutype[i];
3049.     		/* note: separate `style_name' variable used
3050. 		   to avoid an optimizer bug in VAX C V2.3 */
3051. 		any.a_int = i + 1;
3052. 		add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0,
3053. 			 ATR_NONE, style_name, MENU_UNSELECTED);
3054.         }
3055. 	end_menu(tmpwin, "Select menustyle:");
3056. 	if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
3057. 		flags.menu_style = style_pick->item.a_int - 1;
3058. 		free((genericptr_t)style_pick);
3059.         }
3060. 	destroy_nhwindow(tmpwin);
3061.         retval = TRUE;
3062.     } else if (!strcmp("pickup_burden", optname)) {
3063. 	const char *burden_name, *burden_letters = "ubsntl";
3064. 	menu_item *burden_pick = (menu_item *)0;
3065.         tmpwin = create_nhwindow(NHW_MENU);
3066. 	start_menu(tmpwin);
3067. 	for (i = 0; i < SIZE(burdentype); i++) {
3068. 		burden_name = burdentype[i];
3069. 		any.a_int = i + 1;
3070. 		add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0,
3071. 			 ATR_NONE, burden_name, MENU_UNSELECTED);
3072.         }
3073. 	end_menu(tmpwin, "Select encumbrance level:");
3074. 	if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
3075. 		flags.pickup_burden = burden_pick->item.a_int - 1;
3076. 		free((genericptr_t)burden_pick);
3077. 	}
3078. 	destroy_nhwindow(tmpwin);
3079. 	retval = TRUE;
3080.     } else if (!strcmp("pickup_types", optname)) {
3081. 	/* parseoptions will prompt for the list of types */
3082. 	parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
3083. 	retval = TRUE;
3084.     } else if (!strcmp("disclose", optname)) {
3085. 	int pick_cnt, pick_idx, opt_idx;
3086. 	menu_item *disclosure_category_pick = (menu_item *)0;
3087. 	/*
3088. 	 * The order of disclose_names[]
3089.          * must correspond to disclosure_options in decl.h
3090.          */
3091. 	static const char *disclosure_names[] = {
3092. 		"inventory", "attributes", "vanquished", "genocides", "conduct"
3093. 	};
3094. 	int disc_cat[NUM_DISCLOSURE_OPTIONS];
3095. 	const char *disclosure_name;
3096. 
3097.         tmpwin = create_nhwindow(NHW_MENU);
3098. 	start_menu(tmpwin);
3099. 	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
3100. 		disclosure_name = disclosure_names[i];
3101. 		any.a_int = i + 1;
3102. 		add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
3103. 			 ATR_NONE, disclosure_name, MENU_UNSELECTED);
3104. 		disc_cat[i] = 0;
3105.         }
3106. 	end_menu(tmpwin, "Change which disclosure options categories:");
3107. 	if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) {
3108. 	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
3109. 		opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1;
3110. 		disc_cat[opt_idx] = 1;
3111. 	    }
3112. 	    free((genericptr_t)disclosure_category_pick);
3113. 	    disclosure_category_pick = (menu_item *)0;
3114. 	}
3115. 	destroy_nhwindow(tmpwin);
3116. 
3117. 	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
3118. 	    if (disc_cat[i]) {
3119. 	    	char dbuf[BUFSZ];
3120. 		menu_item *disclosure_option_pick = (menu_item *)0;
3121. 		Sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]);
3122. 	        tmpwin = create_nhwindow(NHW_MENU);
3123. 		start_menu(tmpwin);
3124. 		any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
3125. 		add_menu(tmpwin, NO_GLYPH, &any, 'a', 0,
3126. 			ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED);
3127. 		any.a_void = 0;
3128. 		any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
3129. 		add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
3130. 			ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED);
3131. 		any.a_void = 0;
3132. 		any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
3133. 		add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
3134. 			ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED);
3135. 		any.a_void = 0;
3136. 		any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
3137. 		add_menu(tmpwin, NO_GLYPH, &any, 'd', 0,
3138. 			ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED);
3139. 		end_menu(tmpwin, dbuf);
3140. 		if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) {
3141. 			flags.end_disclose[i] = disclosure_option_pick->item.a_char;
3142. 			free((genericptr_t)disclosure_option_pick);
3143. 		}
3144. 		destroy_nhwindow(tmpwin);
3145. 	    }
3146. 	}
3147. 	retval = TRUE;
3148.     } else if (!strcmp("runmode", optname)) {
3149. 	const char *mode_name;
3150. 	menu_item *mode_pick = (menu_item *)0;
3151. 	tmpwin = create_nhwindow(NHW_MENU);
3152. 	start_menu(tmpwin);
3153. 	for (i = 0; i < SIZE(runmodes); i++) {
3154. 		mode_name = runmodes[i];
3155. 		any.a_int = i + 1;
3156. 		add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0,
3157. 			 ATR_NONE, mode_name, MENU_UNSELECTED);
3158. 	}
3159. 	end_menu(tmpwin, "Select run/travel display mode:");
3160. 	if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
3161. 		iflags.runmode = mode_pick->item.a_int - 1;
3162. 		free((genericptr_t)mode_pick);
3163. 	}
3164. 	destroy_nhwindow(tmpwin);
3165. 	retval = TRUE;
3166.     } 
3167. #ifdef TTY_GRAPHICS
3168.       else if (!strcmp("msg_window", optname)) {
3169. 	/* by Christian W. Cooper */
3170. 	menu_item *window_pick = (menu_item *)0;
3171. 	tmpwin = create_nhwindow(NHW_MENU);
3172. 	start_menu(tmpwin);
3173. 	any.a_char = 's';
3174. 	add_menu(tmpwin, NO_GLYPH, &any, 's', 0,
3175. 		ATR_NONE, "single", MENU_UNSELECTED);
3176. 	any.a_char = 'c';
3177. 	add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
3178. 		ATR_NONE, "combination", MENU_UNSELECTED);
3179. 	any.a_char = 'f';
3180. 	add_menu(tmpwin, NO_GLYPH, &any, 'f', 0,
3181. 		ATR_NONE, "full", MENU_UNSELECTED);
3182. 	any.a_char = 'r';
3183. 	add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
3184. 		ATR_NONE, "reversed", MENU_UNSELECTED);
3185. 	end_menu(tmpwin, "Select message history display type:");
3186. 	if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
3187. 		iflags.prevmsg_window = window_pick->item.a_char;
3188. 		free((genericptr_t)window_pick);
3189. 	}
3190. 	destroy_nhwindow(tmpwin);
3191.         retval = TRUE;
3192.     }
3193. #endif
3194.      else if (!strcmp("align_message", optname) ||
3195. 		!strcmp("align_status", optname)) {
3196. 	menu_item *window_pick = (menu_item *)0;
3197. 	char abuf[BUFSZ];
3198. 	boolean msg = (*(optname+6) == 'm');
3199. 
3200. 	tmpwin = create_nhwindow(NHW_MENU);
3201. 	start_menu(tmpwin);
3202. 	any.a_int = ALIGN_TOP;
3203. 	add_menu(tmpwin, NO_GLYPH, &any, 't', 0,
3204. 		ATR_NONE, "top", MENU_UNSELECTED);
3205. 	any.a_int = ALIGN_BOTTOM;
3206. 	add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
3207. 		ATR_NONE, "bottom", MENU_UNSELECTED);
3208. 	any.a_int = ALIGN_LEFT;
3209. 	add_menu(tmpwin, NO_GLYPH, &any, 'l', 0,
3210. 		ATR_NONE, "left", MENU_UNSELECTED);
3211. 	any.a_int = ALIGN_RIGHT;
3212. 	add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
3213. 		ATR_NONE, "right", MENU_UNSELECTED);
3214. 	Sprintf(abuf, "Select %s window placement relative to the map:",
3215. 		msg ? "message" : "status");
3216. 	end_menu(tmpwin, abuf);
3217. 	if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {		
3218. 		if (msg) iflags.wc_align_message = window_pick->item.a_int;
3219. 		else iflags.wc_align_status = window_pick->item.a_int;
3220. 		free((genericptr_t)window_pick);
3221. 	}
3222. 	destroy_nhwindow(tmpwin);
3223.         retval = TRUE;
3224.     } else if (!strcmp("number_pad", optname)) {
3225. 	static const char *npchoices[3] =
3226. 		{"0 (off)", "1 (on)", "2 (on, DOS compatible)"};
3227. 	const char *npletters = "abc";
3228. 	menu_item *mode_pick = (menu_item *)0;
3229. 
3230. 	tmpwin = create_nhwindow(NHW_MENU);
3231. 	start_menu(tmpwin);
3232. 	for (i = 0; i < SIZE(npchoices); i++) {
3233. 		any.a_int = i + 1;
3234. 		add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
3235. 			 ATR_NONE, npchoices[i], MENU_UNSELECTED);
3236.         }
3237. 	end_menu(tmpwin, "Select number_pad mode:");
3238. 	if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
3239. 		int mode = mode_pick->item.a_int - 1;
3240. 		switch(mode) {
3241. 			case 2:
3242. 				iflags.num_pad = 1;
3243. 				iflags.num_pad_mode = 1;
3244. 				break;
3245. 			case 1:
3246. 				iflags.num_pad = 1;
3247. 				iflags.num_pad_mode = 0;
3248. 				break;
3249. 			case 0:
3250. 			default:
3251. 				iflags.num_pad = 0;
3252. 				iflags.num_pad_mode = 0;
3253. 		}
3254. 		free((genericptr_t)mode_pick);
3255. 		number_pad(iflags.num_pad);
3256.         }
3257. 	destroy_nhwindow(tmpwin);
3258.         retval = TRUE;
3259.     } else if (!strcmp("menu_headings", optname)) {
3260. 	static const char *mhchoices[3] = {"bold", "inverse", "underline"};
3261. 	const char *npletters = "biu";
3262. 	menu_item *mode_pick = (menu_item *)0;
3263. 
3264. 	tmpwin = create_nhwindow(NHW_MENU);
3265. 	start_menu(tmpwin);
3266. 	for (i = 0; i < SIZE(mhchoices); i++) {
3267. 		any.a_int = i + 1;
3268. 		add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
3269. 			 ATR_NONE, mhchoices[i], MENU_UNSELECTED);
3270.         }
3271. 	end_menu(tmpwin, "How to highlight menu headings:");
3272. 	if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
3273. 		int mode = mode_pick->item.a_int - 1;
3274. 		switch(mode) {
3275. 			case 2:
3276. 				iflags.menu_headings = ATR_ULINE;
3277. 				break;
3278. 			case 0:
3279. 				iflags.menu_headings = ATR_BOLD;
3280. 				break;
3281. 			case 1:
3282. 			default:
3283. 				iflags.menu_headings = ATR_INVERSE;
3284. 		}
3285. 		free((genericptr_t)mode_pick);
3286.         }
3287. 	destroy_nhwindow(tmpwin);
3288.         retval = TRUE;
3289. #ifdef AUTOPICKUP_EXCEPTIONS
3290.     } else if (!strcmp("autopickup_exception", optname)) {
3291.     	boolean retval;
3292. 	int pick_cnt, pick_idx, opt_idx, pass;
3293. 	int totalapes = 0, numapes[2] = {0,0};
3294. 	menu_item *pick_list = (menu_item *)0;
3295. 	anything any;
3296. 	char apebuf[BUFSZ];
3297. 	struct autopickup_exception *ape;
3298. 	static const char *action_titles[] = {
3299. 		"a", "add new autopickup exception",
3300. 		"l", "list autopickup exceptions",
3301. 		"r", "remove existing autopickup exception",
3302. 		"e", "exit this menu",
3303. 	};
3304. ape_again:
3305. 	opt_idx = 0;
3306. 	totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
3307. 	tmpwin = create_nhwindow(NHW_MENU);
3308. 	start_menu(tmpwin);
3309. 	any.a_int = 0;
3310. 	for (i = 0; i < SIZE(action_titles) ; i += 2) {
3311. 		any.a_int++;
3312. 		if (!totalapes && (i >= 2 && i < 6)) continue;
3313. 		add_menu(tmpwin, NO_GLYPH, &any, *action_titles[i],
3314. 		      0, ATR_NONE, action_titles[i+1], MENU_UNSELECTED);
3315.         }
3316. 	end_menu(tmpwin, "Do what?");
3317. 	if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
3318. 		for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
3319. 			opt_idx = pick_list[pick_idx].item.a_int - 1;
3320. 		}
3321. 		free((genericptr_t)pick_list);
3322. 		pick_list = (menu_item *)0;
3323. 	}
3324. 	destroy_nhwindow(tmpwin);
3325. 	if (pick_cnt < 1) return FALSE;
3326. 
3327. 	if (opt_idx == 0) {	/* add new */
3328. 		getlin("What new autopickup exception pattern?", &apebuf[1]);
3329. 		if (apebuf[1] == '\033') return FALSE;
3330. 		apebuf[0] = '"';
3331. 		Strcat(apebuf,"\"");
3332. 		add_autopickup_exception(apebuf);
3333. 		goto ape_again;
3334. 	} else if (opt_idx == 3) {
3335. 		retval = TRUE;
3336. 	} else {	/* remove */
3337. 		tmpwin = create_nhwindow(NHW_MENU);
3338. 		start_menu(tmpwin);
3339. 		for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
3340. 		    if (numapes[pass] == 0) continue;
3341. 		    ape = iflags.autopickup_exceptions[pass];
3342. 		    any.a_void = 0;
3343. 		    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3344. 				(pass == 0) ? "Never pickup" : "Always pickup",
3345. 				MENU_UNSELECTED);
3346. 		    for (i = 0; i < numapes[pass] && ape; i++) {
3347. 			any.a_void = (opt_idx == 1) ? 0 : ape;
3348. 			Sprintf(apebuf, "\"%s\"", ape->pattern);
3349. 			add_menu(tmpwin, NO_GLYPH, &any,
3350. 				0, 0, ATR_NONE, apebuf, MENU_UNSELECTED);
3351. 			ape = ape->next;
3352. 		    }
3353. 		}
3354. 		Sprintf(apebuf, "%s autopickup exceptions",
3355. 			(opt_idx == 1) ? "List of" : "Remove which");
3356. 		end_menu(tmpwin, apebuf);
3357. 		pick_cnt = select_menu(tmpwin,
3358. 					(opt_idx == 1) ?  PICK_NONE : PICK_ANY,
3359. 					&pick_list);
3360. 		if (pick_cnt > 0) {
3361. 	    	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
3362. 			remove_autopickup_exception(
3363. 			 (struct autopickup_exception *)pick_list[pick_idx].item.a_void);
3364. 	        }
3365. 	        free((genericptr_t)pick_list);
3366. 	        pick_list = (menu_item *)0;
3367. 		destroy_nhwindow(tmpwin);
3368. 		goto ape_again;
3369. 	}
3370. 	retval = TRUE;
3371. #endif /* AUTOPICKUP_EXCEPTIONS */
3372.     }
3373.     return retval;
3374. }
3375. 
3376. #define rolestring(val,array,field) ((val >= 0) ? array[val].field : \
3377. 				     (val == ROLE_RANDOM) ? randomrole : none)
3378. 
3379. /* This is ugly. We have all the option names in the compopt[] array,
3380.    but we need to look at each option individually to get the value. */
3381. STATIC_OVL const char *
3382. get_compopt_value(optname, buf)
3383. const char *optname;
3384. char *buf;
3385. {
3386. 	char ocl[MAXOCLASSES+1];
3387. 	static const char none[] = "(none)", randomrole[] = "random",
3388. 		     to_be_done[] = "(to be done)",
3389. 		     defopt[] = "default",
3390. 		     defbrief[] = "def";
3391. 	int i;
3392. 
3393. 	buf[0] = '\0';
3394. 	if (!strcmp(optname,"align_message"))
3395. 		Sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP     ? "top" :
3396. 				   iflags.wc_align_message == ALIGN_LEFT    ? "left" :
3397. 				   iflags.wc_align_message == ALIGN_BOTTOM  ? "bottom" :
3398. 				   iflags.wc_align_message == ALIGN_RIGHT   ? "right" :
3399. 				   defopt);
3400. 	else if (!strcmp(optname,"align_status"))
3401. 		Sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP     ? "top" :
3402. 				   iflags.wc_align_status == ALIGN_LEFT    ? "left" :
3403. 				   iflags.wc_align_status == ALIGN_BOTTOM  ? "bottom" :
3404. 				   iflags.wc_align_status == ALIGN_RIGHT   ? "right" :
3405. 				   defopt);
3406. 	else if (!strcmp(optname,"align"))
3407. 		Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
3408. #ifdef WIN32CON
3409. 	else if (!strcmp(optname,"altkeyhandler"))
3410. 		Sprintf(buf, "%s", iflags.altkeyhandler[0] ?
3411. 			iflags.altkeyhandler : "default");
3412. #endif
3413. 	else if (!strcmp(optname, "boulder"))
3414. 		Sprintf(buf, "%c", iflags.bouldersym ?
3415. 			iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]);
3416. 	else if (!strcmp(optname, "catname")) 
3417. 		Sprintf(buf, "%s", catname[0] ? catname : none );
3418. 	else if (!strcmp(optname, "disclose")) {
3419. 		for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
3420. 			char topt[2];
3421. 			if (i) Strcat(buf," ");
3422. 			topt[1] = '\0';
3423. 			topt[0] = flags.end_disclose[i];
3424. 			Strcat(buf, topt);
3425. 			topt[0] = disclosure_options[i];
3426. 			Strcat(buf, topt);
3427. 		}
3428. 	}
3429. 	else if (!strcmp(optname, "dogname")) 
3430. 		Sprintf(buf, "%s", dogname[0] ? dogname : none );
3431. 	else if (!strcmp(optname, "dungeon"))
3432. 		Sprintf(buf, "%s", to_be_done);
3433. 	else if (!strcmp(optname, "effects"))
3434. 		Sprintf(buf, "%s", to_be_done);
3435. 	else if (!strcmp(optname, "font_map"))
3436. 		Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
3437. 	else if (!strcmp(optname, "font_message"))
3438. 		Sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt);
3439. 	else if (!strcmp(optname, "font_status"))
3440. 		Sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt);
3441. 	else if (!strcmp(optname, "font_menu"))
3442. 		Sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
3443. 	else if (!strcmp(optname, "font_text"))
3444. 		Sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt);
3445. 	else if (!strcmp(optname, "font_size_map")) {
3446. 		if (iflags.wc_fontsiz_map) Sprintf(buf, "%d", iflags.wc_fontsiz_map);
3447. 		else Strcpy(buf, defopt);
3448. 	}
3449. 	else if (!strcmp(optname, "font_size_message")) {
3450. 		if (iflags.wc_fontsiz_message) Sprintf(buf, "%d",
3451. 							iflags.wc_fontsiz_message);
3452. 		else Strcpy(buf, defopt);
3453. 	}
3454. 	else if (!strcmp(optname, "font_size_status")) {
3455. 		if (iflags.wc_fontsiz_status) Sprintf(buf, "%d", iflags.wc_fontsiz_status);
3456. 		else Strcpy(buf, defopt);
3457. 	}
3458. 	else if (!strcmp(optname, "font_size_menu")) {
3459. 		if (iflags.wc_fontsiz_menu) Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
3460. 		else Strcpy(buf, defopt);
3461. 	}
3462. 	else if (!strcmp(optname, "font_size_text")) {
3463. 		if (iflags.wc_fontsiz_text) Sprintf(buf, "%d",iflags.wc_fontsiz_text);
3464. 		else Strcpy(buf, defopt);
3465. 	}
3466. 	else if (!strcmp(optname, "fruit")) 
3467. 		Sprintf(buf, "%s", pl_fruit);
3468. 	else if (!strcmp(optname, "gender"))
3469. 		Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
3470. 	else if (!strcmp(optname, "ghoulname")) 
3471. 		Sprintf(buf, "%s", ghoulname[0] ? ghoulname : none );
3472. 	else if (!strcmp(optname, "horsename")) 
3473. 		Sprintf(buf, "%s", horsename[0] ? horsename : none);
3474. 	else if (!strcmp(optname, "map_mode"))
3475. 		Sprintf(buf, "%s",
3476. 			iflags.wc_map_mode == MAP_MODE_TILES      ? "tiles" :
3477. 			iflags.wc_map_mode == MAP_MODE_ASCII4x6   ? "ascii4x6" :
3478. 			iflags.wc_map_mode == MAP_MODE_ASCII6x8   ? "ascii6x8" :
3479. 			iflags.wc_map_mode == MAP_MODE_ASCII8x8   ? "ascii8x8" :
3480. 			iflags.wc_map_mode == MAP_MODE_ASCII16x8  ? "ascii16x8" :
3481. 			iflags.wc_map_mode == MAP_MODE_ASCII7x12  ? "ascii7x12" :
3482. 			iflags.wc_map_mode == MAP_MODE_ASCII8x12  ? "ascii8x12" :
3483. 			iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" :
3484. 			iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" :
3485. 			iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" :
3486. 			iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ?
3487. 			"fit_to_screen" : defopt);
3488. 	else if (!strcmp(optname, "menustyle")) 
3489. 		Sprintf(buf, "%s", menutype[(int)flags.menu_style] );
3490. 	else if (!strcmp(optname, "menu_deselect_all"))
3491. 		Sprintf(buf, "%s", to_be_done);
3492. 	else if (!strcmp(optname, "menu_deselect_page"))
3493. 		Sprintf(buf, "%s", to_be_done);
3494. 	else if (!strcmp(optname, "menu_first_page"))
3495. 		Sprintf(buf, "%s", to_be_done);
3496. 	else if (!strcmp(optname, "menu_invert_all"))
3497. 		Sprintf(buf, "%s", to_be_done);
3498. 	else if (!strcmp(optname, "menu_headings")) {
3499. 		Sprintf(buf, "%s", (iflags.menu_headings == ATR_BOLD) ?
3500. 			"bold" :   (iflags.menu_headings == ATR_INVERSE) ?
3501. 			"inverse" :   (iflags.menu_headings == ATR_ULINE) ?
3502. 			"underline" : "unknown");
3503. 	}
3504. 	else if (!strcmp(optname, "menu_invert_page"))
3505. 		Sprintf(buf, "%s", to_be_done);
3506. 	else if (!strcmp(optname, "menu_last_page"))
3507. 		Sprintf(buf, "%s", to_be_done);
3508. 	else if (!strcmp(optname, "menu_next_page"))
3509. 		Sprintf(buf, "%s", to_be_done);
3510. 	else if (!strcmp(optname, "menu_previous_page"))
3511. 		Sprintf(buf, "%s", to_be_done);
3512. 	else if (!strcmp(optname, "menu_search"))
3513. 		Sprintf(buf, "%s", to_be_done);
3514. 	else if (!strcmp(optname, "menu_select_all"))
3515. 		Sprintf(buf, "%s", to_be_done);
3516. 	else if (!strcmp(optname, "menu_select_page"))
3517. 		Sprintf(buf, "%s", to_be_done);
3518. 	else if (!strcmp(optname, "monsters"))
3519. 		Sprintf(buf, "%s", to_be_done);
3520. 	else if (!strcmp(optname, "msghistory"))
3521. 		Sprintf(buf, "%u", iflags.msg_history);
3522. #ifdef TTY_GRAPHICS
3523. 	else if (!strcmp(optname, "msg_window"))
3524. 		Sprintf(buf, "%s", (iflags.prevmsg_window=='s') ? "single" :
3525. 					(iflags.prevmsg_window=='c') ? "combination" :
3526. 					(iflags.prevmsg_window=='f') ? "full" : "reversed");
3527. #endif
3528. 	else if (!strcmp(optname, "name"))
3529. 		Sprintf(buf, "%s", plname);
3530. 	else if (!strcmp(optname, "number_pad"))
3531. 		Sprintf(buf, "%s",
3532. 			(!iflags.num_pad) ? "0=off" :
3533. 			(iflags.num_pad_mode) ? "2=on, DOS compatible" : "1=on");
3534. 	else if (!strcmp(optname, "objects"))
3535. 		Sprintf(buf, "%s", to_be_done);
3536. 	else if (!strcmp(optname, "packorder")) {
3537. 		oc_to_str(flags.inv_order, ocl);
3538. 		Sprintf(buf, "%s", ocl);
3539. 	     }
3540. #ifdef CHANGE_COLOR
3541. 	else if (!strcmp(optname, "palette")) 
3542. 		Sprintf(buf, "%s", get_color_string());
3543. #endif
3544. 	else if (!strcmp(optname, "pettype")) 
3545. 		Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" :
3546. 				(preferred_pet == 'd') ? "dog" :
3547. 				(preferred_pet == 'n') ? "none" : "random");
3548. 	else if (!strcmp(optname, "pickup_burden"))
3549. 		Sprintf(buf, "%s", burdentype[flags.pickup_burden] );
3550. 	else if (!strcmp(optname, "pickup_types")) {
3551. 		oc_to_str(flags.pickup_types, ocl);
3552. 		Sprintf(buf, "%s", ocl[0] ? ocl : "all" );
3553. 	     }
3554. 	else if (!strcmp(optname, "race"))
3555. 		Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
3556. 	else if (!strcmp(optname, "role"))
3557. 		Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
3558. 	else if (!strcmp(optname, "runmode"))
3559. 		Sprintf(buf, "%s", runmodes[iflags.runmode]);
3560. 	else if (!strcmp(optname, "scores")) {
3561. 		Sprintf(buf, "%d top/%d around%s", flags.end_top,
3562. 				flags.end_around, flags.end_own ? "/own" : "");
3563. 	}
3564. 	else if (!strcmp(optname, "scroll_amount")) {
3565. 		if (iflags.wc_scroll_amount) Sprintf(buf, "%d",iflags.wc_scroll_amount);
3566. 		else Strcpy(buf, defopt);
3567. 	}
3568. 	else if (!strcmp(optname, "scroll_margin")) {
3569. 		if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin);
3570. 		else Strcpy(buf, defopt);
3571. 	}
3572. 	else if (!strcmp(optname, "player_selection"))
3573. 		Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
3574. #ifdef MSDOS
3575. 	else if (!strcmp(optname, "soundcard"))
3576. 		Sprintf(buf, "%s", to_be_done);
3577. #endif
3578. 	else if (!strcmp(optname, "suppress_alert")) {
3579. 	    if (flags.suppress_alert == 0L)
3580. 		Strcpy(buf, none);
3581. 	    else
3582. 		Sprintf(buf, "%lu.%lu.%lu",
3583. 			FEATURE_NOTICE_VER_MAJ,
3584. 			FEATURE_NOTICE_VER_MIN,
3585. 			FEATURE_NOTICE_VER_PATCH);
3586. 	}
3587. 	else if (!strcmp(optname, "tile_file"))
3588. 		Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
3589. 	else if (!strcmp(optname, "tile_height")) {
3590. 		if (iflags.wc_tile_height) Sprintf(buf, "%d",iflags.wc_tile_height);
3591. 		else Strcpy(buf, defopt);
3592. 	}
3593. 	else if (!strcmp(optname, "tile_width")) {
3594. 		if (iflags.wc_tile_width) Sprintf(buf, "%d",iflags.wc_tile_width);
3595. 		else Strcpy(buf, defopt);
3596. 	}
3597. 	else if (!strcmp(optname, "tileset")) 
3598. 		Sprintf(buf, "%s", tileset[0] ? tileset : none );
3599. 	else if (!strcmp(optname, "traps"))
3600. 		Sprintf(buf, "%s", to_be_done);
3601. 	else if (!strcmp(optname, "vary_msgcount")) {
3602. 		if (iflags.wc_vary_msgcount) Sprintf(buf, "%d",iflags.wc_vary_msgcount);
3603. 		else Strcpy(buf, defopt);
3604. 	}
3605. #ifdef MSDOS
3606. 	else if (!strcmp(optname, "video"))
3607. 		Sprintf(buf, "%s", to_be_done);
3608. #endif
3609. #ifdef VIDEOSHADES
3610. # ifdef MSDOS
3611. 	else if (!strcmp(optname, "videoshades"))
3612. 		Sprintf(buf, "%s-%s-%s", shade[0],shade[1],shade[2]);
3613. 	else if (!strcmp(optname, "videocolors"))
3614. 		Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
3615. 			ttycolors[CLR_RED], ttycolors[CLR_GREEN],
3616. 			ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
3617. 			ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
3618. 			ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
3619. 			ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
3620. 			ttycolors[CLR_BRIGHT_MAGENTA],
3621. 			ttycolors[CLR_BRIGHT_CYAN]);
3622. # else
3623. 	else if (!strcmp(optname, "videocolors"))
3624. 		Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
3625. 			ttycolors[CLR_RED], ttycolors[CLR_GREEN],
3626. 			ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
3627. 			ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN], 
3628. 			ttycolors[CLR_GRAY], ttycolors[CLR_BLACK],
3629. 			ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
3630. 			ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
3631. 			ttycolors[CLR_BRIGHT_MAGENTA], 
3632. 			ttycolors[CLR_BRIGHT_CYAN], ttycolors[CLR_WHITE]);
3633. # endif /* MSDOS */
3634. #endif /* VIDEOSHADES */
3635. 	else if (!strcmp(optname, "windowtype"))
3636. 		Sprintf(buf, "%s", windowprocs.name);
3637. 	else if (!strcmp(optname, "windowcolors"))
3638. 		Sprintf(buf, "%s/%s %s/%s %s/%s %s/%s",
3639. 			iflags.wc_foregrnd_menu    ? iflags.wc_foregrnd_menu : defbrief,
3640. 			iflags.wc_backgrnd_menu    ? iflags.wc_backgrnd_menu : defbrief,
3641. 			iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief,
3642. 			iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief,
3643. 			iflags.wc_foregrnd_status  ? iflags.wc_foregrnd_status : defbrief,
3644. 			iflags.wc_backgrnd_status  ? iflags.wc_backgrnd_status : defbrief,
3645. 			iflags.wc_foregrnd_text    ? iflags.wc_foregrnd_text : defbrief,
3646. 			iflags.wc_backgrnd_text    ? iflags.wc_backgrnd_text : defbrief);
3647. 	else if (!strcmp(optname, "wolfname")) 
3648. 		Sprintf(buf, "%s", wolfname[0] ? wolfname : none );
3649. #ifdef PREFIXES_IN_USE
3650. 	else {
3651. 	    for (i = 0; i < PREFIX_COUNT; ++i)
3652. 		if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
3653. 			Sprintf(buf, "%s", fqn_prefix[i]);
3654. 	}
3655. #endif
3656. 
3657. 	if (buf[0]) return buf;
3658. 	else return "unknown";
3659. }
3660. 
3661. int
3662. dotogglepickup()
3663. {
3664. 	char buf[BUFSZ], ocl[MAXOCLASSES+1];
3665. 
3666. 	flags.pickup = !flags.pickup;
3667. 	if (flags.pickup) {
3668. 	    oc_to_str(flags.pickup_types, ocl);
3669. 	    Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
3670. #ifdef AUTOPICKUP_EXCEPTIONS
3671. 			(iflags.autopickup_exceptions[AP_LEAVE] ||
3672. 			 iflags.autopickup_exceptions[AP_GRAB]) ?
3673. 			 ((count_ape_maps((int *)0, (int *)0) == 1) ?
3674. 			    ", with one exception" : ", with some exceptions") :
3675. #endif
3676. 			"");
3677. 	} else {
3678. 	    Strcpy(buf, "OFF");
3679. 	}
3680. 	pline("Autopickup: %s.", buf);
3681. 	return 0;
3682. }
3683. 
3684. #ifdef AUTOPICKUP_EXCEPTIONS
3685. int
3686. add_autopickup_exception(mapping)
3687. const char *mapping;
3688. {
3689. 	struct autopickup_exception *ape, **apehead;
3690. 	char text[256], *text2;
3691. 	int textsize = 0;
3692. 	boolean grab = FALSE;
3693. 
3694. 	if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
3695. 		text2 = &text[0];
3696. 		if (*text2 == '<') {		/* force autopickup */
3697. 			grab = TRUE;
3698. 			++text2;
3699. 		} else if (*text2 == '>') {	/* default - Do not pickup */
3700. 			grab = FALSE;
3701. 			++text2;
3702. 		}
3703. 		textsize = strlen(text2);
3704. 		apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] :
3705. 				   &iflags.autopickup_exceptions[AP_LEAVE];
3706. 		ape = (struct autopickup_exception *)
3707. 				alloc(sizeof(struct autopickup_exception));
3708. 		ape->pattern = (char *) alloc(textsize+1);
3709. 		Strcpy(ape->pattern, text2);
3710. 		ape->grab = grab;
3711. 		if (!*apehead) ape->next = (struct autopickup_exception *)0;
3712. 		else ape->next = *apehead;
3713. 		*apehead = ape;
3714. 	} else {
3715. 	    raw_print("syntax error in AUTOPICKUP_EXCEPTION");
3716. 	    return 0;
3717. 	}
3718. 	return 1;
3719. }
3720. 
3721. STATIC_OVL void
3722. remove_autopickup_exception(whichape)
3723. struct autopickup_exception *whichape;
3724. {
3725.     struct autopickup_exception *ape, *prev = 0;
3726.     int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
3727. 
3728.     for (ape = iflags.autopickup_exceptions[chain]; ape;) {
3729. 	if (ape == whichape) {
3730. 	    struct autopickup_exception *freeape = ape;
3731. 	    ape = ape->next;
3732. 	    if (prev) prev->next = ape;
3733. 	    else iflags.autopickup_exceptions[chain] = ape;
3734. 	    free(freeape->pattern);
3735. 	    free(freeape);
3736. 	} else {
3737. 	    prev = ape;
3738. 	    ape = ape->next;
3739. 	}
3740.     }
3741. }
3742. 
3743. STATIC_OVL int
3744. count_ape_maps(leave, grab)
3745. int *leave, *grab;
3746. {
3747. 	struct autopickup_exception *ape;
3748. 	int pass, totalapes, numapes[2] = {0,0};
3749. 
3750. 	for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
3751. 		ape = iflags.autopickup_exceptions[pass];
3752. 		while(ape) {
3753. 			ape = ape->next;
3754. 			numapes[pass]++;
3755. 		}
3756. 	}
3757. 	totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
3758. 	if (leave) *leave = numapes[AP_LEAVE];
3759. 	if (grab) *grab = numapes[AP_GRAB];
3760. 	return totalapes;
3761. }
3762. 
3763. void
3764. free_autopickup_exceptions()
3765. {
3766. 	struct autopickup_exception *ape;
3767. 	int pass;
3768. 
3769. 	for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
3770. 		while((ape = iflags.autopickup_exceptions[pass]) != 0) {
3771. 			free(ape->pattern);
3772. 			iflags.autopickup_exceptions[pass] = ape->next;
3773. 			free(ape);
3774. 		}
3775. 	}
3776. }
3777. #endif /* AUTOPICKUP_EXCEPTIONS */
3778. 
3779. /* data for option_help() */
3780. static const char *opt_intro[] = {
3781. 	"",
3782. 	"                 SlashEM Options Help:",
3783. 	"",
3784. #define CONFIG_SLOT 3	/* fill in next value at run-time */
3785. 	(char *)0,
3786. #define ENV_SLOT 4	/* substitute variable name in next value at run-time */
3787. #if !defined(MICRO) && !defined(MAC)
3788. 	"or use `%s=\"<options>\"' in your environment",
3789. #endif
3790. 	"(<options> is a list of options separated by commas)",
3791. #ifdef VMS
3792.   	"-- for example, $ DEFINE %s \"noautopickup,fruit:kumquat\"",
3793. #endif
3794. 	"or press \"O\" while playing and use the menu.",
3795. 	"",
3796.  "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
3797. 	(char *)0
3798. };
3799. 
3800. static const char *opt_epilog[] = {
3801. 	"",
3802.  "Some of the options can be set only before the game is started; those",
3803. 	"items will not be selectable in the 'O' command's menu.",
3804. 	(char *)0
3805. };
3806. 
3807. void
3808. option_help()
3809. {
3810.     char buf[BUFSZ], buf2[BUFSZ];
3811.     register int i;
3812.     winid datawin;
3813. 
3814.     datawin = create_nhwindow(NHW_TEXT);
3815.     Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
3816.     opt_intro[CONFIG_SLOT] = (const char *) buf;
3817.     for (i = 0; opt_intro[i]; i++)
3818. 	if (i==ENV_SLOT)
3819. 	{
3820. 	    Sprintf(buf2, opt_intro[ENV_SLOT], NETHACK_ENV_OPTIONS);
3821. 	    putstr(datawin, 0, buf2);;
3822. 	}
3823. 	else
3824. 	putstr(datawin, 0, opt_intro[i]);
3825. 
3826.     /* Boolean options */
3827.     for (i = 0; boolopt[i].name; i++) {
3828. 	if (boolopt[i].addr) {
3829. #ifdef WIZARD
3830. #ifndef OBJ_SANITY
3831. 	    if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue;
3832. #endif
3833. 	    if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue;
3834. #endif
3835. 	    next_opt(datawin, boolopt[i].name);
3836. 	}
3837.     }
3838.     next_opt(datawin, "");
3839. 
3840.     /* Compound options */
3841.     putstr(datawin, 0, "Compound options:");
3842.     for (i = 0; compopt[i].name; i++) {
3843. 	Sprintf(buf2, "`%s'", compopt[i].name);
3844. 	Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
3845. 		compopt[i+1].name ? ',' : '.');
3846. 	putstr(datawin, 0, buf);
3847.     }
3848. 
3849.     for (i = 0; opt_epilog[i]; i++)
3850. 	putstr(datawin, 0, opt_epilog[i]);
3851. 
3852.     display_nhwindow(datawin, FALSE);
3853.     destroy_nhwindow(datawin);
3854.     return;
3855. }
3856. 
3857. /*
3858.  * prints the next boolean option, on the same line if possible, on a new
3859.  * line if not. End with next_opt("").
3860.  */
3861. void
3862. next_opt(datawin, str)
3863. winid datawin;
3864. const char *str;
3865. {
3866. 	static char *buf = 0;
3867. 	int i;
3868. 	char *s;
3869. 
3870. 	if (!buf) *(buf = (char *)alloc(BUFSZ)) = '\0';
3871. 
3872. 	if (!*str) {
3873. 		s = eos(buf);
3874. 		if (s > &buf[1] && s[-2] == ',')
3875. 		    Strcpy(s - 2, ".");	/* replace last ", " */
3876. 		i = COLNO;	/* (greater than COLNO - 2) */
3877. 	} else {
3878. 		i = strlen(buf) + strlen(str) + 2;
3879. 	}
3880. 
3881. 	if (i > COLNO - 2) { /* rule of thumb */
3882. 		putstr(datawin, 0, buf);
3883. 		buf[0] = 0;
3884. 	}
3885. 	if (*str) {
3886. 		Strcat(buf, str);
3887. 		Strcat(buf, ", ");
3888. 	} else {
3889. 		putstr(datawin, 0, str);
3890. 		free(buf),  buf = 0;
3891. 	}
3892. 	return;
3893. }
3894. 
3895. /* Returns the fid of the fruit type; if that type already exists, it
3896.  * returns the fid of that one; if it does not exist, it adds a new fruit
3897.  * type to the chain and returns the new one.
3898.  */
3899. int
3900. fruitadd(str)
3901. char *str;
3902. {
3903. 	register int i;
3904. 	register struct fruit *f;
3905. 	struct fruit *lastf = 0;
3906. 	int highest_fruit_id = 0;
3907. 	char buf[PL_FSIZ];
3908. 	boolean user_specified = (str == pl_fruit);
3909. 	/* if not user-specified, then it's a fruit name for a fruit on
3910. 	 * a bones level...
3911. 	 */
3912. 
3913. 	/* Note: every fruit has an id (spe for fruit objects) of at least
3914. 	 * 1; 0 is an error.
3915. 	 */
3916. 	if (user_specified) {
3917. 		/* disallow naming after other foods (since it'd be impossible
3918. 		 * to tell the difference)
3919. 		 */
3920. 
3921. 		boolean found = FALSE, numeric = FALSE;
3922. 
3923. 		for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS;
3924. 						i++) {
3925. 			if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
3926. 				found = TRUE;
3927. 				break;
3928. 			}
3929. 		}
3930. 		{
3931. 		    char *c;
3932. 
3933. 		    c = pl_fruit;
3934. 
3935. 		    for(c = pl_fruit; *c >= '0' && *c <= '9'; c++)
3936. 			;
3937. 		    if (isspace(*c) || *c == 0) numeric = TRUE;
3938. 		}
3939. 		if (found || numeric ||
3940. 		    !strncmp(str, "cursed ", 7) ||
3941. 		    !strncmp(str, "uncursed ", 9) ||
3942. 		    !strncmp(str, "blessed ", 8) ||
3943. 		    !strncmp(str, "partly eaten ", 13) ||
3944. 		    (!strncmp(str, "tin of ", 7) &&
3945. 			(!strcmp(str+7, "spinach") ||
3946. 			 name_to_mon(str+7) >= LOW_PM)) ||
3947. 		    !strcmp(str, "empty tin") ||
3948. 		    ((!strncmp(eos(str)-7," corpse",7) ||
3949. 			    !strncmp(eos(str)-4, " egg",4)) &&
3950. 			name_to_mon(str) >= LOW_PM))
3951. 			{
3952. 				Strcpy(buf, pl_fruit);
3953. 				Strcpy(pl_fruit, "candied ");
3954. 				nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
3955. 		}
3956. 	}
3957. 	for(f=ffruit; f; f = f->nextf) {
3958. 		lastf = f;
3959. 		if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
3960. 		if(!strncmp(str, f->fname, PL_FSIZ))
3961. 			goto nonew;
3962. 	}
3963. 	/* if adding another fruit would overflow spe, use a random
3964. 	   fruit instead... we've got a lot to choose from. */
3965. 	if (highest_fruit_id >= 127) return rnd(127);
3966. 	highest_fruit_id++;
3967. 	f = newfruit();
3968. 	if (ffruit) lastf->nextf = f;
3969. 	else ffruit = f;
3970. 	Strcpy(f->fname, str);
3971. 	f->fid = highest_fruit_id;
3972. 	f->nextf = 0;
3973. nonew:
3974. 	if (user_specified) current_fruit = highest_fruit_id;
3975. 	return f->fid;
3976. }
3977. 
3978. /*
3979.  * This is a somewhat generic menu for taking a list of NetHack style
3980.  * class choices and presenting them via a description
3981.  * rather than the traditional NetHack characters.
3982.  * (Benefits users whose first exposure to NetHack is via tiles).
3983.  *
3984.  * prompt
3985.  *	     The title at the top of the menu.
3986.  *
3987.  * category: 0 = monster class
3988.  *           1 = object  class
3989.  *
3990.  * way
3991.  *	     FALSE = PICK_ONE, TRUE = PICK_ANY
3992.  *
3993.  * class_list
3994.  *	     a null terminated string containing the list of choices.
3995.  *
3996.  * class_selection
3997.  *	     a null terminated string containing the selected characters.
3998.  *
3999.  * Returns number selected.
4000.  */
4001. int
4002. choose_classes_menu(prompt, category, way, class_list, class_select)
4003. const char *prompt;
4004. int category;
4005. boolean way;
4006. char *class_list;
4007. char *class_select;
4008. {
4009.     menu_item *pick_list = (menu_item *)0;
4010.     winid win;
4011.     anything any;
4012.     char buf[BUFSZ];
4013.     int i, n;
4014.     int ret;
4015.     int next_accelerator, accelerator;
4016. 
4017.     if (class_list == (char *)0 || class_select == (char *)0) return 0;
4018.     accelerator = 0;
4019.     next_accelerator = 'a';
4020.     any.a_void = 0;
4021.     win = create_nhwindow(NHW_MENU);
4022.     start_menu(win);
4023.     while (*class_list) {
4024. 	const char *text;
4025. 	boolean selected;
4026. 
4027. 	text = (char *)0;
4028. 	selected = FALSE;
4029. 	switch (category) {
4030. 		case 0:
4031. 			text = monexplain[def_char_to_monclass(*class_list)];
4032. 			accelerator = *class_list;
4033. 			Sprintf(buf, "%s", text);
4034. 			break;
4035. 		case 1:
4036. 			text = objexplain[def_char_to_objclass(*class_list)];
4037. 			accelerator = next_accelerator;
4038. 			Sprintf(buf, "%c  %s", *class_list, text);
4039. 			break;
4040. 		default:
4041. 			impossible("choose_classes_menu: invalid category %d",
4042. 					category);
4043. 	}
4044. 	if (way && *class_select) {	/* Selections there already */
4045. 		if (index(class_select, *class_list)) {
4046. 			selected = TRUE;
4047. 		}
4048. 	}
4049. 	any.a_int = *class_list;
4050. 	add_menu(win, NO_GLYPH, &any, accelerator,
4051. 		  category ? *class_list : 0,
4052. 		  ATR_NONE, buf, selected);
4053. 	++class_list;
4054. 	if (category > 0) {
4055. 		++next_accelerator;
4056. 		if (next_accelerator == ('z' + 1)) next_accelerator = 'A';
4057. 		if (next_accelerator == ('Z' + 1)) break;
4058. 	}
4059.     }
4060.     end_menu(win, prompt);
4061.     n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
4062.     destroy_nhwindow(win);
4063.     if (n > 0) {
4064. 	for (i = 0; i < n; ++i)
4065. 	    *class_select++ = (char)pick_list[i].item.a_int;
4066. 	free((genericptr_t)pick_list);
4067. 	ret = n;
4068.     } else if (n == -1) {
4069. 	class_select = eos(class_select);
4070. 	ret = -1;
4071.     } else
4072. 	ret = 0;
4073.     *class_select = '\0';
4074.     return ret;
4075. }
4076. 
4077. struct wc_Opt wc_options[] = {
4078. 	{"ascii_map", WC_ASCII_MAP},
4079. 	{"color", WC_COLOR},
4080. 	{"eight_bit_tty", WC_EIGHT_BIT_IN},
4081. 	{"hilite_pet", WC_HILITE_PET},
4082. 	{"popup_dialog", WC_POPUP_DIALOG},
4083. 	{"player_selection", WC_PLAYER_SELECTION},
4084. 	{"preload_tiles", WC_PRELOAD_TILES},
4085. 	{"tiled_map", WC_TILED_MAP},
4086. 	{"tile_file", WC_TILE_FILE},
4087. 	{"tile_width", WC_TILE_WIDTH},
4088. 	{"tile_height", WC_TILE_HEIGHT},
4089. 	{"use_inverse", WC_INVERSE},
4090. 	{"align_message", WC_ALIGN_MESSAGE},
4091. 	{"align_status", WC_ALIGN_STATUS},
4092. 	{"font_map", WC_FONT_MAP},
4093. 	{"font_menu", WC_FONT_MENU},
4094. 	{"font_message",WC_FONT_MESSAGE},
4095. #if 0
4096. 	{"perm_invent",WC_PERM_INVENT},
4097. #endif
4098. 	{"font_size_map", WC_FONTSIZ_MAP},
4099. 	{"font_size_menu", WC_FONTSIZ_MENU},
4100. 	{"font_size_message", WC_FONTSIZ_MESSAGE},
4101. 	{"font_size_status", WC_FONTSIZ_STATUS},
4102. 	{"font_size_text", WC_FONTSIZ_TEXT},
4103. 	{"font_status", WC_FONT_STATUS},
4104. 	{"font_text", WC_FONT_TEXT},
4105. 	{"map_mode", WC_MAP_MODE},
4106. 	{"scroll_amount", WC_SCROLL_AMOUNT},
4107. 	{"scroll_margin", WC_SCROLL_MARGIN},
4108. 	{"splash_screen", WC_SPLASH_SCREEN},
4109. 	{"vary_msgcount",WC_VARY_MSGCOUNT},
4110. 	{"windowcolors", WC_WINDOWCOLORS},
4111. 	{"mouse_support", WC_MOUSE_SUPPORT},
4112. 	{(char *)0, 0L}
4113. };
4114. 
4115. struct wc_Opt wc2_options[] = {
4116. 	{"fullscreen", WC2_FULLSCREEN},
4117. 	{"softkeyboard", WC2_SOFTKEYBOARD},
4118. 	{"wraptext", WC2_WRAPTEXT},
4119. 	{(char *)0, 0L}
4120. };
4121. 
4122. 
4123. /*
4124.  * If a port wants to change or ensure that the
4125.  * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
4126.  * correct (for controlling its display in the option menu) call
4127.  * set_option_mod_status()
4128.  * with the second argument of 0,2, or 3 respectively.
4129.  */
4130. void
4131. set_option_mod_status(optnam, status)
4132. const char *optnam;
4133. int status;
4134. {
4135. 	int k;
4136. 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
4137. 		impossible("set_option_mod_status: status out of range %d.",
4138. 			   status);
4139. 		return;
4140. 	}
4141. 	for (k = 0; boolopt[k].name; k++) {
4142. 		if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
4143. 			boolopt[k].optflags = status;
4144. 			return;
4145. 		}
4146. 	}
4147. 	for (k = 0; compopt[k].name; k++) {
4148. 		if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
4149. 			compopt[k].optflags = status;
4150. 			return;
4151. 		}
4152. 	}
4153. }
4154. 
4155. /*
4156.  * You can set several wc_options in one call to
4157.  * set_wc_option_mod_status() by setting
4158.  * the appropriate bits for each option that you
4159.  * are setting in the optmask argument
4160.  * prior to calling.
4161.  *    example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME);
4162.  */
4163. void
4164. set_wc_option_mod_status(optmask, status)
4165. unsigned long optmask;
4166. int status;
4167. {
4168. 	int k = 0;
4169. 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
4170. 		impossible("set_wc_option_mod_status: status out of range %d.",
4171. 			   status);
4172. 		return;
4173. 	}
4174. 	while (wc_options[k].wc_name) {
4175. 		if (optmask & wc_options[k].wc_bit) {
4176. 			set_option_mod_status(wc_options[k].wc_name, status);
4177. 		}
4178. 		k++;
4179. 	}
4180. }
4181. 
4182. STATIC_OVL boolean
4183. is_wc_option(optnam)
4184. const char *optnam;
4185. {
4186. 	int k = 0;
4187. 	while (wc_options[k].wc_name) {
4188. 		if (strcmp(wc_options[k].wc_name, optnam) == 0)
4189. 			return TRUE;
4190. 		k++;
4191. 	}
4192. 	return FALSE;
4193. }
4194. 
4195. STATIC_OVL boolean
4196. wc_supported(optnam)
4197. const char *optnam;
4198. {
4199. 	int k = 0;
4200. 	while (wc_options[k].wc_name) {
4201. 		if (!strcmp(wc_options[k].wc_name, optnam) &&
4202. 		    (windowprocs.wincap & wc_options[k].wc_bit))
4203. 			return TRUE;
4204. 		k++;
4205. 	}
4206. 	return FALSE;
4207. }
4208. 
4209. 
4210. /*
4211.  * You can set several wc2_options in one call to
4212.  * set_wc2_option_mod_status() by setting
4213.  * the appropriate bits for each option that you
4214.  * are setting in the optmask argument
4215.  * prior to calling.
4216.  *    example: set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT, SET_IN_FILE);
4217.  */
4218. 
4219. void
4220. set_wc2_option_mod_status(optmask, status)
4221. unsigned long optmask;
4222. int status;
4223. {
4224. 	int k = 0;
4225. 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
4226. 		impossible("set_wc2_option_mod_status: status out of range %d.",
4227. 			   status);
4228. 		return;
4229. 	}
4230. 	while (wc2_options[k].wc_name) {
4231. 		if (optmask & wc2_options[k].wc_bit) {
4232. 			set_option_mod_status(wc2_options[k].wc_name, status);
4233. 		}
4234. 		k++;
4235. 	}
4236. }
4237. 
4238. STATIC_OVL boolean
4239. is_wc2_option(optnam)
4240. const char *optnam;
4241. {
4242. 	int k = 0;
4243. 	while (wc2_options[k].wc_name) {
4244. 		if (strcmp(wc2_options[k].wc_name, optnam) == 0)
4245. 			return TRUE;
4246. 		k++;
4247. 	}
4248. 	return FALSE;
4249. }
4250. 
4251. STATIC_OVL boolean
4252. wc2_supported(optnam)
4253. const char *optnam;
4254. {
4255. 	int k = 0;
4256. 	while (wc2_options[k].wc_name) {
4257. 		if (!strcmp(wc2_options[k].wc_name, optnam) &&
4258. 		    (windowprocs.wincap2 & wc2_options[k].wc_bit))
4259. 			return TRUE;
4260. 		k++;
4261. 	}
4262. 	return FALSE;
4263. }
4264. 
4265. 
4266. STATIC_OVL void
4267. wc_set_font_name(wtype, fontname)
4268. int wtype;
4269. char *fontname;
4270. {
4271. 	char **fn = (char **)0;
4272. 	if (!fontname) return;
4273. 	switch(wtype) {
4274. 	    case NHW_MAP:
4275. 	    		fn = &iflags.wc_font_map;
4276. 			break;
4277. 	    case NHW_MESSAGE:
4278. 	    		fn = &iflags.wc_font_message;
4279. 			break;
4280. 	    case NHW_TEXT:
4281. 	    		fn = &iflags.wc_font_text;
4282. 			break;
4283. 	    case NHW_MENU:
4284. 	    		fn = &iflags.wc_font_menu;
4285. 			break;
4286. 	    case NHW_STATUS:
4287. 	    		fn = &iflags.wc_font_status;
4288. 			break;
4289. 	    default:
4290. 	    		return;
4291. 	}
4292. 	if (fn) {
4293. 		if (*fn) free(*fn);
4294. 		*fn = (char *)alloc(strlen(fontname) + 1);
4295. 		Strcpy(*fn, fontname);
4296. 	}
4297. 	return;
4298. }
4299. 
4300. STATIC_OVL int
4301. wc_set_window_colors(op)
4302. char *op;
4303. {
4304. 	/* syntax:
4305. 	 *  menu white/black message green/yellow status white/blue text white/black
4306. 	 */
4307. 
4308. 	int j;
4309. 	char buf[BUFSZ];
4310. 	char *wn, *tfg, *tbg, *newop;
4311. 	static const char *wnames[] = { "menu", "message", "status", "text" };
4312. 	static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
4313. 	static char **fgp[] = {
4314. 		&iflags.wc_foregrnd_menu,
4315. 		&iflags.wc_foregrnd_message,
4316. 		&iflags.wc_foregrnd_status,
4317. 		&iflags.wc_foregrnd_text
4318. 	};
4319. 	static char **bgp[] = {
4320. 		&iflags.wc_backgrnd_menu,
4321. 		&iflags.wc_backgrnd_message,
4322. 		&iflags.wc_backgrnd_status,
4323. 		&iflags.wc_backgrnd_text
4324. 	};
4325. 
4326. 	Strcpy(buf, op);
4327. 	newop = mungspaces(buf);
4328. 	while (newop && *newop) {
4329. 
4330. 		wn = tfg = tbg = (char *)0;
4331. 
4332. 		/* until first non-space in case there's leading spaces - before colorname*/
4333. 		while(*newop && isspace(*newop)) newop++;
4334. 		if (*newop) wn = newop;
4335. 		else return 0;
4336. 
4337. 		/* until first space - colorname*/
4338. 		while(*newop && !isspace(*newop)) newop++;
4339. 		if (*newop) *newop = '\0';
4340. 		else return 0;
4341. 		newop++;
4342. 
4343. 		/* until first non-space - before foreground*/
4344. 		while(*newop && isspace(*newop)) newop++;
4345. 		if (*newop) tfg = newop;
4346. 		else return 0;
4347. 
4348. 		/* until slash - foreground */
4349. 		while(*newop && *newop != '/') newop++;
4350. 		if (*newop) *newop = '\0';
4351. 		else return 0;
4352. 		newop++;
4353. 
4354. 		/* until first non-space (in case there's leading space after slash) - before background */
4355. 		while(*newop && isspace(*newop)) newop++;
4356. 		if (*newop) tbg = newop;
4357. 		else return 0;
4358. 
4359. 		/* until first space - background */
4360. 		while(*newop && !isspace(*newop)) newop++;
4361. 		if (*newop) *newop++ = '\0';
4362. 
4363. 		for (j = 0; j < 4; ++j) {
4364. 			if (!strcmpi(wn, wnames[j]) ||
4365. 			    !strcmpi(wn, shortnames[j])) {
4366. 				if (tfg && !strstri(tfg, " ")) {
4367. 					if (*fgp[j]) free(*fgp[j]);
4368. 					*fgp[j] = (char *)alloc(strlen(tfg) + 1);
4369. 					Strcpy(*fgp[j], tfg);
4370. 				}
4371. 				if (tbg && !strstri(tbg, " ")) {
4372. 					if (*bgp[j]) free(*bgp[j]);
4373. 					*bgp[j] = (char *)alloc(strlen(tbg) + 1);
4374. 					Strcpy(*bgp[j], tbg);
4375. 				}
4376.  				break;
4377. 			}
4378. 		}
4379. 	}
4380. 	return 1;
4381. }
4382. 
4383. #endif	/* OPTION_LISTS_ONLY */
4384. /*options.c*/

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.