Source:SLASH'EM 0.0.7E7F2/options.c

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.

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  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. 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=\" \"' in your environment", 3789. #endif 3790. 	"( 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= 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*/