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. */
5 #ifdef OPTION_LISTS_ONLY /* (AMIGA) external program for opt lists */
9 NEARDATA struct flag flags; /* provide linkage */
10 NEARDATA struct instance_flags iflags; /* provide linkage */
20 #ifdef DEFAULT_WC_TILED_MAP
21 #define PREFER_TILED TRUE
23 #define PREFER_TILED FALSE
27 * NOTE: If you add (or delete) an option, please update the short
28 * options help (option_help()), the long options help (dat/opthelp),
29 * and the current options setting display function (doset()),
30 * and also the Guidebooks.
32 * The order matters. If an option is a an initial substring of another
33 * option (e.g. time and timed_delay) the shorter one must come first.
36 static struct Bool_Opt
39 boolean *addr, initvalue;
43 {"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME},
45 {"altmeta", (boolean *)0, TRUE, DISP_IN_GAME},
47 {"ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME}, /*WC*/
49 {"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME},
51 {"asksavedisk", (boolean *)0, FALSE, SET_IN_FILE},
53 {"autodig", &flags.autodig, FALSE, SET_IN_GAME},
54 {"autopickup", &flags.pickup, TRUE, SET_IN_GAME},
55 {"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME},
56 #if defined(MICRO) && !defined(AMIGA)
57 {"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE},
59 {"BIOS", (boolean *)0, FALSE, SET_IN_FILE},
62 {"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME},
64 {"checkpoint", (boolean *)0, FALSE, SET_IN_FILE},
67 {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME},
69 {"checkspace", (boolean *)0, FALSE, SET_IN_FILE},
71 {"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME},
72 # if defined(MICRO) || defined(WIN32)
73 {"color", &iflags.wc_color,TRUE, SET_IN_GAME}, /*WC*/
74 # else /* systems that support multiple terminals, many monochrome */
75 {"color", &iflags.wc_color, FALSE, SET_IN_GAME}, /*WC*/
77 {"confirm",&flags.confirm, TRUE, SET_IN_GAME},
78 #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
79 {"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
81 {"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE},
83 {"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME}, /*WC*/
85 {"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME},
87 {"extmenu", (boolean *)0, FALSE, SET_IN_FILE},
90 {"fast_map", &flags.fast_map, TRUE, SET_IN_GAME},
92 {"fast_map", (boolean *)0, TRUE, SET_IN_FILE},
94 {"female", &flags.female, FALSE, DISP_IN_GAME},
95 {"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME},
97 {"flush", &flags.amiflush, FALSE, SET_IN_GAME},
99 {"flush", (boolean *)0, FALSE, SET_IN_FILE},
101 {"fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE},
102 {"help", &flags.help, TRUE, SET_IN_GAME},
103 {"hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME}, /*WC*/
105 {"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME},
107 {"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE},
110 {"ignintr", &flags.ignintr, FALSE, SET_IN_GAME},
112 {"ignintr", (boolean *)0, FALSE, SET_IN_FILE},
114 {"large_font", &iflags.obsolete, FALSE, SET_IN_FILE}, /* OBSOLETE */
115 {"legacy", &flags.legacy, TRUE, DISP_IN_GAME},
116 {"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME},
117 {"lootabc", &iflags.lootabc, FALSE, SET_IN_GAME},
118 #ifdef MAC_GRAPHICS_ENV
119 {"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME},
121 {"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE},
124 {"mail", &flags.biff, TRUE, SET_IN_GAME},
126 {"mail", (boolean *)0, TRUE, SET_IN_FILE},
129 /* for menu debugging only*/
130 {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME},
132 {"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE},
134 {"mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME}, /*WC*/
136 {"news", &iflags.news, TRUE, DISP_IN_GAME},
138 {"news", (boolean *)0, FALSE, SET_IN_FILE},
140 {"null", &flags.null, TRUE, SET_IN_GAME},
142 {"page_wait", &flags.page_wait, TRUE, SET_IN_GAME},
144 {"page_wait", (boolean *)0, FALSE, SET_IN_FILE},
146 {"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME},
147 {"popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME}, /*WC*/
148 {"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME},
149 {"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME}, /*WC*/
150 {"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME},
151 #if defined(MICRO) && !defined(AMIGA)
152 {"rawio", &iflags.rawio, FALSE, DISP_IN_GAME},
154 {"rawio", (boolean *)0, FALSE, SET_IN_FILE},
156 {"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME},
157 {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
159 {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
161 {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
164 {"showexp", &flags.showexp, FALSE, SET_IN_GAME},
166 {"showexp", (boolean *)0, FALSE, SET_IN_FILE},
168 {"showrace", &iflags.showrace, FALSE, SET_IN_GAME},
170 {"showscore", &flags.showscore, FALSE, SET_IN_GAME},
172 {"showscore", (boolean *)0, FALSE, SET_IN_FILE},
174 {"silent", &flags.silent, TRUE, SET_IN_GAME},
175 {"softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE},
176 {"sortpack", &flags.sortpack, TRUE, SET_IN_GAME},
177 {"sound", &flags.soundok, TRUE, SET_IN_GAME},
178 {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
179 {"standout", &flags.standout, FALSE, SET_IN_GAME},
180 {"splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME}, /*WC*/
181 {"tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME}, /*WC*/
182 {"time", &flags.time, FALSE, SET_IN_GAME},
184 {"timed_delay", &flags.nap, TRUE, SET_IN_GAME},
186 {"timed_delay", (boolean *)0, FALSE, SET_IN_GAME},
188 {"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
189 {"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
190 {"travel", &iflags.travelcmd, TRUE, SET_IN_GAME},
192 {"use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME}, /*WC*/
194 {"use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME}, /*WC*/
196 {"verbose", &flags.verbose, TRUE, SET_IN_GAME},
197 {"wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME},
198 {(char *)0, (boolean *)0, FALSE, 0}
201 /* compound options, for option_help() and external programs like Amiga
203 static struct Comp_Opt
205 const char *name, *descr;
206 int size; /* for frontends and such allocating space --
207 * usually allowed size of data in game, but
208 * occasionally maximum reasonable size for
209 * typing when game maintains information in
210 * a different format */
213 { "align", "your starting alignment (lawful, neutral, or chaotic)",
215 { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
216 { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/
217 { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
218 { "boulder", "the symbol to use for displaying boulders",
220 { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
221 PL_PSIZ, DISP_IN_GAME },
222 { "disclose", "the kinds of information to disclose at end of game",
223 sizeof(flags.end_disclose) * 2,
225 { "dogname", "the name of your (first) dog (e.g., dogname:Fang)",
226 PL_PSIZ, DISP_IN_GAME },
227 { "dungeon", "the symbols to use in drawing the dungeon map",
228 MAXDCHARS+1, SET_IN_FILE },
229 { "effects", "the symbols to use in drawing special effects",
230 MAXECHARS+1, SET_IN_FILE },
231 { "font_map", "the font to use in the map window", 40, DISP_IN_GAME }, /*WC*/
232 { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
233 { "font_message", "the font to use in the message window",
234 40, DISP_IN_GAME }, /*WC*/
235 { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
236 { "font_size_menu", "the size of the menu font", 20, DISP_IN_GAME }, /*WC*/
237 { "font_size_message", "the size of the message font", 20, DISP_IN_GAME }, /*WC*/
238 { "font_size_status", "the size of the status font", 20, DISP_IN_GAME }, /*WC*/
239 { "font_size_text", "the size of the text font", 20, DISP_IN_GAME }, /*WC*/
240 { "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/
241 { "font_text", "the font to use in text windows", 40, DISP_IN_GAME }, /*WC*/
242 { "fruit", "the name of a fruit you enjoy eating",
243 PL_FSIZ, SET_IN_GAME },
244 { "gender", "your starting gender (male or female)",
246 { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
247 PL_PSIZ, DISP_IN_GAME },
248 { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
249 { "menustyle", "user interface for object selection",
250 MENUTYPELEN, SET_IN_GAME },
251 { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
252 { "menu_deselect_page", "deselect all items on this page of a menu",
254 { "menu_first_page", "jump to the first page in a menu",
256 { "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME },
257 { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
258 { "menu_invert_page", "invert all items on this page of a menu",
260 { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
261 { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
262 { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
263 { "menu_search", "search for a menu item", 4, SET_IN_FILE },
264 { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
265 { "menu_select_page", "select all items on this page of a menu",
267 { "monsters", "the symbols to use for monsters",
268 MAXMCLASSES, SET_IN_FILE },
269 { "msghistory", "number of top line messages to save",
272 {"msg_window", "the type of message window required",1, SET_IN_GAME},
274 {"msg_window", "the type of message window required", 1, SET_IN_FILE},
276 { "name", "your character's name (e.g., name:Merlin-W)",
277 PL_NSIZ, DISP_IN_GAME },
278 { "number_pad", "use the number pad", 1, SET_IN_GAME},
279 { "objects", "the symbols to use for objects",
280 MAXOCLASSES, SET_IN_FILE },
281 { "packorder", "the inventory order of the items in your pack",
282 MAXOCLASSES, SET_IN_GAME },
284 { "palette", "palette (00c/880/-fff is blue/yellow/reverse white)",
287 { "hicolor", "same as palette, only order is reversed",
291 { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
292 { "pickup_burden", "maximum burden picked up before prompt",
294 { "pickup_types", "types of objects to pick up automatically",
295 MAXOCLASSES, SET_IN_GAME },
296 { "player_selection", "choose character via dialog or prompts",
298 { "race", "your starting race (e.g., Human, Elf)",
299 PL_CSIZ, DISP_IN_GAME },
300 { "role", "your starting role (e.g., Barbarian, Valkyrie)",
301 PL_CSIZ, DISP_IN_GAME },
302 { "runmode", "display frequency when `running' or `travelling'",
303 sizeof "teleport", SET_IN_GAME },
304 { "scores", "the parts of the score list you wish to see",
306 { "scroll_amount", "amount to scroll map when scroll_margin is reached",
307 20, DISP_IN_GAME }, /*WC*/
308 { "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
310 { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
312 { "suppress_alert", "suppress alerts about version-specific features",
314 { "tile_width", "width of tiles", 20, DISP_IN_GAME}, /*WC*/
315 { "tile_height", "height of tiles", 20, DISP_IN_GAME}, /*WC*/
316 { "tile_file", "name of tile file", 70, DISP_IN_GAME}, /*WC*/
317 { "traps", "the symbols to use in drawing traps",
318 MAXTCHARS+1, SET_IN_FILE },
319 { "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/
321 { "video", "method of video updating", 20, SET_IN_FILE },
324 { "videocolors", "color mappings for internal screen routines",
326 { "videoshades", "gray shades to map to black/gray/white",
330 {"subkeyvalue", "override keystroke value", 7, SET_IN_FILE},
332 { "windowcolors", "the foreground/background colors of windows", /*WC*/
334 { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
335 { (char *)0, (char *)0, 0, 0 }
338 #ifdef OPTION_LISTS_ONLY
341 #else /* use rest of file */
343 static boolean need_redraw; /* for doset() */
345 #if defined(TOS) && defined(TEXTCOLOR)
346 extern boolean colors_changed; /* in tos.c */
350 extern char *shade[3]; /* in sys/msdos/video.c */
351 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
354 static char def_inv_order[MAXOCLASSES] = {
355 COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
356 SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
357 TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
361 * Default menu manipulation command accelerators. These may _not_ be:
363 * + a number - reserved for counts
364 * + an upper or lower case US ASCII letter - used for accelerators
365 * + ESC - reserved for escaping the menu
366 * + NULL, CR or LF - reserved for commiting the selection(s). NULL
367 * is kind of odd, but the tty's xwaitforspace() will return it if
368 * someone hits a <ret>.
369 * + a default object class symbol - used for object class accelerators
371 * Standard letters (for now) are:
384 * The command name list is duplicated in the compopt array.
391 #define NUM_MENU_CMDS 11
392 static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
393 /* 0*/ { "menu_first_page", MENU_FIRST_PAGE },
394 { "menu_last_page", MENU_LAST_PAGE },
395 { "menu_next_page", MENU_NEXT_PAGE },
396 { "menu_previous_page", MENU_PREVIOUS_PAGE },
397 { "menu_select_all", MENU_SELECT_ALL },
398 /* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL },
399 { "menu_invert_all", MENU_INVERT_ALL },
400 { "menu_select_page", MENU_SELECT_PAGE },
401 { "menu_deselect_page", MENU_UNSELECT_PAGE },
402 { "menu_invert_page", MENU_INVERT_PAGE },
403 /*10*/ { "menu_search", MENU_SEARCH },
407 * Allow the user to map incoming characters to various menu commands.
408 * The accelerator list must be a valid C string.
410 #define MAX_MENU_MAPPED_CMDS 32 /* some number */
411 char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1]; /* exported */
412 static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1];
413 static short n_menu_mapped = 0;
416 static boolean initial, from_file;
418 STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int));
419 STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
420 STATIC_DCL void FDECL(escapes, (const char *, char *));
421 STATIC_DCL void FDECL(rejectoption, (const char *));
422 STATIC_DCL void FDECL(badoption, (const char *));
423 STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P));
424 STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *,BOOLEAN_P));
425 STATIC_DCL void FDECL(bad_negation, (const char *,BOOLEAN_P));
426 STATIC_DCL int FDECL(change_inv_order, (char *));
427 STATIC_DCL void FDECL(oc_to_str, (char *, char *));
428 STATIC_DCL void FDECL(graphics_opts, (char *,const char *,int,int));
429 STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
430 STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
431 STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P));
432 STATIC_DCL void FDECL(warning_opts, (char *,const char *));
433 STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int));
435 STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
436 STATIC_OVL int FDECL(wc_set_window_colors, (char *));
437 STATIC_OVL boolean FDECL(is_wc_option, (const char *));
438 STATIC_OVL boolean FDECL(wc_supported, (const char *));
439 STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
440 STATIC_OVL boolean FDECL(wc2_supported, (const char *));
441 #ifdef AUTOPICKUP_EXCEPTIONS
442 STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *));
443 STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
446 /* check whether a user-supplied option string is a proper leading
447 substring of a particular option name; option string might have
448 a colon or equals sign and arbitrary value appended to it */
450 match_optname(user_string, opt_name, min_length, val_allowed)
451 const char *user_string, *opt_name;
455 int len = (int)strlen(user_string);
458 const char *p = index(user_string, ':'),
459 *q = index(user_string, '=');
461 if (!p || (q && q < p)) p = q;
462 while(p && p > user_string && isspace(*(p-1))) p--;
463 if (p) len = (int)(p - user_string);
466 return (len >= min_length) && !strncmpi(opt_name, user_string, len);
469 /* most environment variables will eventually be printed in an error
470 * message if they don't work, and most error message paths go through
471 * BUFSZ buffers, which could be overflowed by a maliciously long
472 * environment variable. if a variable can legitimately be long, or
473 * if it's put in a smaller buffer, the responsible code will have to
474 * bounds-check itself.
480 char *getev = getenv(ev);
482 if (getev && strlen(getev) <= (BUFSZ / 2))
496 /* initialize the random number generator */
499 /* for detection of configfile options specified multiple times */
500 iflags.opt_booldup = iflags.opt_compdup = (int *)0;
502 for (i = 0; boolopt[i].name; i++) {
504 *(boolopt[i].addr) = boolopt[i].initvalue;
506 flags.end_own = FALSE;
508 flags.end_around = 2;
509 iflags.runmode = RUN_LEAP;
510 iflags.msg_history = 20;
512 iflags.prevmsg_window = 's';
514 iflags.menu_headings = ATR_INVERSE;
516 /* Use negative indices to indicate not yet selected */
520 flags.initalign = -1;
522 /* Set the default monster and object class symbols. Don't use */
523 /* memcpy() --- sizeof char != sizeof uchar on some machines. */
524 for (i = 0; i < MAXOCLASSES; i++)
525 oc_syms[i] = (uchar) def_oc_syms[i];
526 for (i = 0; i < MAXMCLASSES; i++)
527 monsyms[i] = (uchar) def_monsyms[i];
528 for (i = 0; i < WARNCOUNT; i++)
529 warnsyms[i] = def_warnsyms[i].sym;
530 iflags.bouldersym = 0;
531 iflags.travelcc.x = iflags.travelcc.y = -1;
535 /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
536 (void)memcpy((genericptr_t)flags.inv_order,
537 (genericptr_t)def_inv_order, sizeof flags.inv_order);
538 flags.pickup_types[0] = '\0';
539 flags.pickup_burden = MOD_ENCUMBER;
541 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
542 flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
543 switch_graphics(ASCII_GRAPHICS); /* set default characters */
544 #if defined(UNIX) && defined(TTY_GRAPHICS)
546 * Set defaults for some options depending on what we can
547 * detect about the environment's capabilities.
548 * This has to be done after the global initialization above
549 * and before reading user-specific initialization via
550 * config file/environment variable below.
552 /* this detects the IBM-compatible console on most 386 boxes */
553 if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
554 switch_graphics(IBM_GRAPHICS);
556 iflags.use_color = TRUE;
559 #endif /* UNIX && TTY_GRAPHICS */
560 #if defined(UNIX) || defined(VMS)
562 /* detect whether a "vt" terminal can handle alternate charsets */
563 if ((opts = nh_getenv("TERM")) &&
564 !strncmpi(opts, "vt", 2) && AS && AE &&
565 index(AS, '\016') && index(AE, '\017')) {
566 switch_graphics(DEC_GRAPHICS);
569 #endif /* UNIX || VMS */
571 #ifdef MAC_GRAPHICS_ENV
572 switch_graphics(MAC_GRAPHICS);
573 #endif /* MAC_GRAPHICS_ENV */
574 flags.menu_style = MENU_FULL;
576 /* since this is done before init_objects(), do partial init here */
577 objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
578 nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
580 opts = getenv("NETHACKOPTIONS");
581 if (!opts) opts = getenv("HACKOPTIONS");
583 if (*opts == '/' || *opts == '\\' || *opts == '@') {
584 if (*opts == '@') opts++; /* @filename */
585 /* looks like a filename */
586 if (strlen(opts) < BUFSZ/2)
587 read_config_file(opts);
589 read_config_file((char *)0);
590 /* let the total length of options be long;
591 * parseoptions() will check each individually
593 parseoptions(opts, TRUE, FALSE);
597 read_config_file((char *)0);
599 (void)fruitadd(pl_fruit);
600 /* Remove "slime mold" from list of object names; this will */
601 /* prevent it from being wished unless it's actually present */
602 /* as a named (or default) fruit. Wishing for "fruit" will */
603 /* result in the player's preferred fruit [better than "\033"]. */
604 obj_descr[SLIME_MOLD].oc_name = "fruit";
610 nmcpy(dest, src, maxlen)
617 for(count = 1; count < maxlen; count++) {
618 if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
625 * escapes: escape expansion for showsyms. C-style escapes understood include
626 * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
627 * for control characters is also understood, and \[mM] followed by any of the
628 * previous forms or by a character has the effect of 'meta'-ing the value (so
629 * that the alternate character set will be enabled).
638 int cval = 0, meta = 0;
640 if (*cp == '\\' && index("mM", cp[1])) {
644 if (*cp == '\\' && index("0123456789xXoO", cp[1]))
646 const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
650 if (*cp == 'x' || *cp == 'X')
651 for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
652 cval = (cval * 16) + (dp - hex) / 2;
653 else if (*cp == 'o' || *cp == 'O')
654 for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
655 cval = (cval * 8) + (*cp - '0');
657 for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
658 cval = (cval * 10) + (*cp - '0');
660 else if (*cp == '\\') /* C-style character escapes */
664 case '\\': cval = '\\'; break;
665 case 'n': cval = '\n'; break;
666 case 't': cval = '\t'; break;
667 case 'b': cval = '\b'; break;
668 case 'r': cval = '\r'; break;
673 else if (*cp == '^') /* expand control-character syntax */
675 cval = (*++cp & 0x1f);
688 rejectoption(optname)
692 pline("\"%s\" settable only from %s.", optname, configfile);
694 pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
704 if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
707 pline("Bad syntax: %s. Enter \"?g\" for help.", opts);
715 raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
717 raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts);
723 string_for_opt(opts, val_optional)
725 boolean val_optional;
727 char *colon, *equals;
729 colon = index(opts, ':');
730 equals = index(opts, '=');
731 if (!colon || (equals && equals < colon)) colon = equals;
733 if (!colon || !*++colon) {
734 if (!val_optional) badoption(opts);
741 string_for_env_opt(optname, opts, val_optional)
744 boolean val_optional;
747 rejectoption(optname);
750 return string_for_opt(opts, val_optional);
754 bad_negation(optname, with_parameter)
756 boolean with_parameter;
758 pline_The("%s option may not %sbe negated.",
760 with_parameter ? "both have a value and " : "");
764 * Change the inventory order, using the given string as the new order.
765 * Missing characters in the new order are filled in at the end from
766 * the current inv_order, except for gold, which is forced to be first
767 * if not explicitly present.
769 * This routine returns 1 unless there is a duplicate or bad char in
777 char *sp, buf[BUFSZ];
781 if (!index(op, GOLD_SYM))
782 buf[num++] = COIN_CLASS;
784 /* !!!! probably unnecessary with gold as normal inventory */
787 for (sp = op; *sp; sp++) {
788 oc_sym = def_char_to_objclass(*sp);
789 /* reject bad or duplicate entries */
790 if (oc_sym == MAXOCLASSES ||
791 oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS ||
792 !index(flags.inv_order, oc_sym) || index(sp+1, *sp))
794 /* retain good ones */
795 buf[num++] = (char) oc_sym;
799 /* fill in any omitted classes, using previous ordering */
800 for (sp = flags.inv_order; *sp; sp++)
801 if (!index(buf, *sp)) {
803 buf[num] = '\0'; /* explicitly terminate for next index() */
806 Strcpy(flags.inv_order, buf);
811 graphics_opts(opts, optype, maxlen, offset)
816 uchar translate[MAXPCHARS+1];
819 if (!(opts = string_for_env_opt(optype, opts, FALSE)))
823 length = strlen(opts);
824 if (length > maxlen) length = maxlen;
825 /* match the form obtained from PC configuration files */
826 for (i = 0; i < length; i++)
827 translate[i] = (uchar) opts[i];
828 assign_graphics(translate, length, maxlen, offset);
832 warning_opts(opts, optype)
836 uchar translate[MAXPCHARS+1];
839 if (!(opts = string_for_env_opt(optype, opts, FALSE)))
843 length = strlen(opts);
844 if (length > WARNCOUNT) length = WARNCOUNT;
845 /* match the form obtained from PC configuration files */
846 for (i = 0; i < length; i++)
847 translate[i] = (((i < WARNCOUNT) && opts[i]) ?
848 (uchar) opts[i] : def_warnsyms[i].sym);
849 assign_warnings(translate);
853 assign_warnings(graph_chars)
854 register uchar *graph_chars;
857 for (i = 0; i < WARNCOUNT; i++)
858 if (graph_chars[i]) warnsyms[i] = graph_chars[i];
862 feature_alert_opts(op, optn)
867 boolean rejectver = FALSE;
868 unsigned long fnv = get_feature_notice_ver(op); /* version.c */
869 if (fnv == 0L) return 0;
870 if (fnv > get_current_feature_ver())
873 flags.suppress_alert = fnv;
876 You_cant("disable new feature alerts for future versions.");
879 "\n%s=%s Invalid reference to a future version ignored",
886 Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
887 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
888 pline("Feature change alerts disabled for NetHack %s features and prior.",
895 set_duplicate_opt_detection(on_or_off)
899 if (on_or_off != 0) {
901 if (iflags.opt_booldup)
902 impossible("iflags.opt_booldup already on (memory leak)");
903 iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int));
904 optptr = iflags.opt_booldup;
905 for (k = 0; k < SIZE(boolopt); ++k)
908 if (iflags.opt_compdup)
909 impossible("iflags.opt_compdup already on (memory leak)");
910 iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int));
911 optptr = iflags.opt_compdup;
912 for (k = 0; k < SIZE(compopt); ++k)
916 if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup);
917 iflags.opt_booldup = (int *)0;
918 if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup);
919 iflags.opt_compdup = (int *)0;
924 duplicate_opt_detection(opts, bool_or_comp)
926 int bool_or_comp; /* 0 == boolean option, 1 == compound */
930 /* the Mac has trouble dealing with the output of messages while
931 * processing the config file. That should get fixed one day.
932 * For now just return.
936 if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) {
937 for (i = 0; boolopt[i].name; i++) {
938 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
939 optptr = iflags.opt_booldup + i;
942 "\nWarning - Boolean option specified multiple times: %s.\n",
947 break; /* don't match multiple options */
950 } else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) {
951 for (i = 0; compopt[i].name; i++) {
952 if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) {
953 optptr = iflags.opt_compdup + i;
956 "\nWarning - compound option specified multiple times: %s.\n",
961 break; /* don't match multiple options */
968 parseoptions(opts, tinitial, tfrom_file)
970 boolean tinitial, tfrom_file;
976 const char *fullname;
979 from_file = tfrom_file;
980 if ((op = index(opts, ',')) != 0) {
982 parseoptions(op, initial, from_file);
984 if (strlen(opts) > BUFSZ/2) {
985 badoption("option too long");
989 /* strip leading and trailing white space */
990 while (isspace(*opts)) opts++;
992 while (--op >= opts && isspace(*op)) *op = '\0';
996 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
997 if (*opts == '!') opts++; else opts += 2;
1001 /* variant spelling */
1003 if (match_optname(opts, "colour", 5, FALSE))
1004 Strcpy(opts, "color"); /* fortunately this isn't longer */
1006 if (!match_optname(opts, "subkeyvalue", 11, TRUE)) /* allow multiple */
1007 duplicate_opt_detection(opts, 1); /* 1 means compound opts */
1009 /* special boolean options */
1011 if (match_optname(opts, "female", 3, FALSE)) {
1012 if(!initial && flags.female == negated)
1013 pline("That is not anatomically possible.");
1015 flags.initgend = flags.female = !negated;
1019 if (match_optname(opts, "male", 4, FALSE)) {
1020 if(!initial && flags.female != negated)
1021 pline("That is not anatomically possible.");
1023 flags.initgend = flags.female = negated;
1027 #if defined(MICRO) && !defined(AMIGA)
1028 /* included for compatibility with old NetHack.cnf files */
1029 if (match_optname(opts, "IBM_", 4, FALSE)) {
1030 iflags.BIOS = !negated;
1035 /* compound options */
1037 fullname = "pettype";
1038 if (match_optname(opts, fullname, 3, TRUE)) {
1039 if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
1040 if (negated) bad_negation(fullname, TRUE);
1044 preferred_pet = 'd';
1048 case 'f': /* feline */
1050 preferred_pet = 'c';
1052 case 'n': /* no pet */
1054 preferred_pet = 'n';
1057 pline("Unrecognized pet type '%s'.", op);
1060 } else if (negated) preferred_pet = 'n';
1064 fullname = "catname";
1065 if (match_optname(opts, fullname, 3, TRUE)) {
1066 if (negated) bad_negation(fullname, FALSE);
1067 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1068 nmcpy(catname, op, PL_PSIZ);
1072 fullname = "dogname";
1073 if (match_optname(opts, fullname, 3, TRUE)) {
1074 if (negated) bad_negation(fullname, FALSE);
1075 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1076 nmcpy(dogname, op, PL_PSIZ);
1080 fullname = "horsename";
1081 if (match_optname(opts, fullname, 5, TRUE)) {
1082 if (negated) bad_negation(fullname, FALSE);
1083 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1084 nmcpy(horsename, op, PL_PSIZ);
1088 fullname = "number_pad";
1089 if (match_optname(opts, fullname, 10, TRUE)) {
1090 boolean compat = (strlen(opts) <= 10);
1091 number_pad(iflags.num_pad ? 1 : 0);
1092 op = string_for_opt(opts, (compat || !initial));
1094 if (compat || negated || initial) {
1095 /* for backwards compatibility, "number_pad" without a
1096 value is a synonym for number_pad:1 */
1097 iflags.num_pad = !negated;
1098 if (iflags.num_pad) iflags.num_pad_mode = 0;
1103 bad_negation("number_pad", TRUE);
1106 if (*op == '1' || *op == '2') {
1108 if (*op == '2') iflags.num_pad_mode = 1;
1109 else iflags.num_pad_mode = 0;
1110 } else if (*op == '0') {
1112 iflags.num_pad_mode = 0;
1113 } else badoption(opts);
1117 fullname = "runmode";
1118 if (match_optname(opts, fullname, 4, TRUE)) {
1120 iflags.runmode = RUN_TPORT;
1121 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
1122 if (!strncmpi(op, "teleport", strlen(op)))
1123 iflags.runmode = RUN_TPORT;
1124 else if (!strncmpi(op, "run", strlen(op)))
1125 iflags.runmode = RUN_LEAP;
1126 else if (!strncmpi(op, "walk", strlen(op)))
1127 iflags.runmode = RUN_STEP;
1128 else if (!strncmpi(op, "crawl", strlen(op)))
1129 iflags.runmode = RUN_CRAWL;
1136 fullname = "msghistory";
1137 if (match_optname(opts, fullname, 3, TRUE)) {
1138 op = string_for_env_opt(fullname, opts, negated);
1139 if ((negated && !op) || (!negated && op)) {
1140 iflags.msg_history = negated ? 0 : atoi(op);
1141 } else if (negated) bad_negation(fullname, TRUE);
1145 fullname="msg_window";
1146 /* msg_window:single, combo, full or reversed */
1147 if (match_optname(opts, fullname, 4, TRUE)) {
1148 /* allow option to be silently ignored by non-tty ports */
1151 if (!(op = string_for_opt(opts, TRUE))) {
1152 tmp = negated ? 's' : 'f';
1155 bad_negation(fullname, TRUE);
1161 case 's': /* single message history cycle (default if negated) */
1162 iflags.prevmsg_window = 's';
1164 case 'c': /* combination: two singles, then full page reversed */
1165 iflags.prevmsg_window = 'c';
1167 case 'f': /* full page (default if no opts) */
1168 iflags.prevmsg_window = 'f';
1170 case 'r': /* full page (reversed) */
1171 iflags.prevmsg_window = 'r';
1181 * setting font options */
1183 if (!strncmpi(opts, fullname, 4))
1186 char *fontopts = opts + 4;
1188 if (!strncmpi(fontopts, "map", 3) ||
1189 !strncmpi(fontopts, "_map", 4))
1191 else if (!strncmpi(fontopts, "message", 7) ||
1192 !strncmpi(fontopts, "_message", 8))
1193 wintype = NHW_MESSAGE;
1194 else if (!strncmpi(fontopts, "text", 4) ||
1195 !strncmpi(fontopts, "_text", 5))
1197 else if (!strncmpi(fontopts, "menu", 4) ||
1198 !strncmpi(fontopts, "_menu", 5))
1200 else if (!strncmpi(fontopts, "status", 6) ||
1201 !strncmpi(fontopts, "_status", 7))
1202 wintype = NHW_STATUS;
1203 else if (!strncmpi(fontopts, "_size", 5)) {
1204 if (!strncmpi(fontopts, "_size_map", 8))
1206 else if (!strncmpi(fontopts, "_size_message", 12))
1207 wintype = NHW_MESSAGE;
1208 else if (!strncmpi(fontopts, "_size_text", 9))
1210 else if (!strncmpi(fontopts, "_size_menu", 9))
1212 else if (!strncmpi(fontopts, "_size_status", 11))
1213 wintype = NHW_STATUS;
1218 if (wintype > 0 && !negated &&
1219 (op = string_for_opt(opts, FALSE)) != 0) {
1222 iflags.wc_fontsiz_map = atoi(op);
1225 iflags.wc_fontsiz_message = atoi(op);
1228 iflags.wc_fontsiz_text = atoi(op);
1231 iflags.wc_fontsiz_menu = atoi(op);
1234 iflags.wc_fontsiz_status = atoi(op);
1243 (op = string_for_opt(opts, FALSE)) != 0) {
1244 wc_set_font_name(wintype, op);
1246 set_font_name (wintype, op);
1249 } else if (negated) bad_negation(fullname, TRUE);
1253 if (match_optname(opts, "palette", 3, TRUE)
1255 || match_optname(opts, "hicolor", 3, TRUE)
1258 int color_number, color_incr;
1261 if (match_optname(opts, "hicolor", 3, TRUE)) {
1263 bad_negation("hicolor", FALSE);
1266 color_number = CLR_MAX + 4; /* HARDCODED inverse number */
1271 bad_negation("palette", FALSE);
1279 if ((op = string_for_opt(opts, FALSE)) != (char *)0) {
1281 int cnt, tmp, reverse;
1284 while (*pt && color_number >= 0) {
1294 if (*pt && *pt != '/') {
1302 tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
1304 tmp &= 0xf; /* Digits in ASCII too... */
1307 /* Add an extra so we fill f -> ff and 0 -> 00 */
1316 change_color(color_number, rgb, reverse);
1317 color_number += color_incr;
1325 #endif /* CHANGE_COLOR */
1327 if (match_optname(opts, "fruit", 2, TRUE)) {
1328 char empty_str = '\0';
1329 op = string_for_opt(opts, negated);
1332 bad_negation("fruit", TRUE);
1343 for(f=ffruit; f; f=f->nextf) {
1344 if (!strcmp(op, f->fname)) goto goodfruit;
1348 pline("Doing that so many times isn't very fruitful.");
1353 nmcpy(pl_fruit, op, PL_FSIZ);
1354 /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
1356 nmcpy(pl_fruit, "slime mold", PL_FSIZ);
1358 (void)fruitadd(pl_fruit);
1359 /* If initial, then initoptions is allowed to do it instead
1360 * of here (initoptions always has to do it even if there's
1361 * no fruit option at all. Also, we don't want people
1362 * setting multiple fruits in their options.)
1367 /* graphics:string */
1368 fullname = "graphics";
1369 if (match_optname(opts, fullname, 2, TRUE)) {
1370 if (negated) bad_negation(fullname, FALSE);
1371 else graphics_opts(opts, fullname, MAXPCHARS, 0);
1374 fullname = "dungeon";
1375 if (match_optname(opts, fullname, 2, TRUE)) {
1376 if (negated) bad_negation(fullname, FALSE);
1377 else graphics_opts(opts, fullname, MAXDCHARS, 0);
1381 if (match_optname(opts, fullname, 2, TRUE)) {
1382 if (negated) bad_negation(fullname, FALSE);
1383 else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS);
1386 fullname = "effects";
1387 if (match_optname(opts, fullname, 2, TRUE)) {
1388 if (negated) bad_negation(fullname, FALSE);
1390 graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS);
1394 /* objects:string */
1395 fullname = "objects";
1396 if (match_optname(opts, fullname, 7, TRUE)) {
1400 bad_negation(fullname, FALSE);
1403 if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1405 escapes(opts, opts);
1408 * Override the default object class symbols. The first
1409 * object in the object class is the "random object". I
1410 * don't want to use 0 as an object class, so the "random
1411 * object" is basically a place holder.
1413 * The object class symbols have already been initialized in
1416 length = strlen(opts);
1417 if (length >= MAXOCLASSES)
1418 length = MAXOCLASSES-1; /* don't count RANDOM_OBJECT */
1420 for (i = 0; i < length; i++)
1421 oc_syms[i+1] = (uchar) opts[i];
1425 /* monsters:string */
1426 fullname = "monsters";
1427 if (match_optname(opts, fullname, 8, TRUE)) {
1431 bad_negation(fullname, FALSE);
1434 if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
1436 escapes(opts, opts);
1438 /* Override default mon class symbols set in initoptions(). */
1439 length = strlen(opts);
1440 if (length >= MAXMCLASSES)
1441 length = MAXMCLASSES-1; /* mon class 0 unused */
1443 for (i = 0; i < length; i++)
1444 monsyms[i+1] = (uchar) opts[i];
1447 fullname = "warnings";
1448 if (match_optname(opts, fullname, 5, TRUE)) {
1449 if (negated) bad_negation(fullname, FALSE);
1450 else warning_opts(opts, fullname);
1453 /* boulder:symbol */
1454 fullname = "boulder";
1455 if (match_optname(opts, fullname, 7, TRUE)) {
1458 bad_negation(fullname, FALSE);
1461 /* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */
1462 if (!(opts = string_for_opt(opts, FALSE)))
1464 escapes(opts, opts);
1465 if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
1467 else if (opts[0] >= '1' && opts[0] <= '5')
1470 /* symbol chosen matches a used monster or warning
1471 symbol which is not good - reject it*/
1473 "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
1474 opts[0], (clash == 1) ? "monster" : "warning");
1477 * Override the default boulder symbol.
1479 iflags.bouldersym = (uchar) opts[0];
1481 if (!initial) need_redraw = TRUE;
1487 if (match_optname(opts, fullname, 4, TRUE)) {
1488 if (negated) bad_negation(fullname, FALSE);
1489 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1490 nmcpy(plname, op, PL_NSIZ);
1494 /* role:string or character:string */
1496 if (match_optname(opts, fullname, 4, TRUE) ||
1497 match_optname(opts, (fullname = "character"), 4, TRUE)) {
1498 if (negated) bad_negation(fullname, FALSE);
1499 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1500 if ((flags.initrole = str2role(op)) == ROLE_NONE)
1502 else /* Backwards compatibility */
1503 nmcpy(pl_character, op, PL_NSIZ);
1510 if (match_optname(opts, fullname, 4, TRUE)) {
1511 if (negated) bad_negation(fullname, FALSE);
1512 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1513 if ((flags.initrace = str2race(op)) == ROLE_NONE)
1515 else /* Backwards compatibility */
1522 fullname = "gender";
1523 if (match_optname(opts, fullname, 4, TRUE)) {
1524 if (negated) bad_negation(fullname, FALSE);
1525 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1526 if ((flags.initgend = str2gend(op)) == ROLE_NONE)
1529 flags.female = flags.initgend;
1534 /* altkeyhandler:string */
1535 fullname = "altkeyhandler";
1536 if (match_optname(opts, fullname, 4, TRUE)) {
1537 if (negated) bad_negation(fullname, FALSE);
1538 else if ((op = string_for_opt(opts, negated))) {
1540 (void)strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
1541 load_keyboard_handler();
1548 * align_status:[left|top|right|bottom] */
1549 fullname = "align_status";
1550 if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) {
1551 op = string_for_opt(opts, negated);
1552 if (op && !negated) {
1553 if (!strncmpi (op, "left", sizeof("left")-1))
1554 iflags.wc_align_status = ALIGN_LEFT;
1555 else if (!strncmpi (op, "top", sizeof("top")-1))
1556 iflags.wc_align_status = ALIGN_TOP;
1557 else if (!strncmpi (op, "right", sizeof("right")-1))
1558 iflags.wc_align_status = ALIGN_RIGHT;
1559 else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1560 iflags.wc_align_status = ALIGN_BOTTOM;
1563 } else if (negated) bad_negation(fullname, TRUE);
1567 * align_message:[left|top|right|bottom] */
1568 fullname = "align_message";
1569 if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) {
1570 op = string_for_opt(opts, negated);
1571 if (op && !negated) {
1572 if (!strncmpi (op, "left", sizeof("left")-1))
1573 iflags.wc_align_message = ALIGN_LEFT;
1574 else if (!strncmpi (op, "top", sizeof("top")-1))
1575 iflags.wc_align_message = ALIGN_TOP;
1576 else if (!strncmpi (op, "right", sizeof("right")-1))
1577 iflags.wc_align_message = ALIGN_RIGHT;
1578 else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
1579 iflags.wc_align_message = ALIGN_BOTTOM;
1582 } else if (negated) bad_negation(fullname, TRUE);
1587 if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) {
1588 if (negated) bad_negation(fullname, FALSE);
1589 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1590 if ((flags.initalign = str2align(op)) == ROLE_NONE)
1595 /* the order to list the pack */
1596 fullname = "packorder";
1597 if (match_optname(opts, fullname, 4, TRUE)) {
1599 bad_negation(fullname, FALSE);
1601 } else if (!(op = string_for_opt(opts, FALSE))) return;
1603 if (!change_inv_order(op))
1608 /* maximum burden picked up before prompt (Warren Cheung) */
1609 fullname = "pickup_burden";
1610 if (match_optname(opts, fullname, 8, TRUE)) {
1612 bad_negation(fullname, FALSE);
1614 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
1615 switch (tolower(*op)) {
1618 flags.pickup_burden = UNENCUMBERED;
1620 /* Burdened (slight encumbrance) */
1622 flags.pickup_burden = SLT_ENCUMBER;
1624 /* streSsed (moderate encumbrance) */
1626 flags.pickup_burden = MOD_ENCUMBER;
1628 /* straiNed (heavy encumbrance) */
1630 flags.pickup_burden = HVY_ENCUMBER;
1632 /* OverTaxed (extreme encumbrance) */
1635 flags.pickup_burden = EXT_ENCUMBER;
1639 flags.pickup_burden = OVERLOADED;
1648 /* types of objects to pick up automatically */
1649 if (match_optname(opts, "pickup_types", 8, TRUE)) {
1650 char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
1651 qbuf[QBUFSZ], abuf[BUFSZ];
1653 boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
1655 oc_to_str(flags.pickup_types, tbuf);
1656 flags.pickup_types[0] = '\0'; /* all */
1657 op = string_for_opt(opts, (compat || !initial));
1659 if (compat || negated || initial) {
1660 /* for backwards compatibility, "pickup" without a
1661 value is a synonym for autopickup of all types
1662 (and during initialization, we can't prompt yet) */
1663 flags.pickup = !negated;
1666 oc_to_str(flags.inv_order, ocl);
1668 if (flags.menu_style == MENU_TRADITIONAL ||
1669 flags.menu_style == MENU_COMBINATION) {
1671 Sprintf(qbuf, "New pickup_types: [%s am] (%s)",
1672 ocl, *tbuf ? tbuf : "all");
1674 op = mungspaces(abuf);
1675 if (abuf[0] == '\0' || abuf[0] == '\033')
1676 op = tbuf; /* restore */
1677 else if (abuf[0] == 'm')
1681 (void) choose_classes_menu("Auto-Pickup what?", 1,
1687 bad_negation("pickup_types", TRUE);
1690 while (*op == ' ') op++;
1691 if (*op != 'a' && *op != 'A') {
1694 oc_sym = def_char_to_objclass(*op);
1695 /* make sure all are valid obj symbols occuring once */
1696 if (oc_sym != MAXOCLASSES &&
1697 !index(flags.pickup_types, oc_sym)) {
1698 flags.pickup_types[num] = (char)oc_sym;
1699 flags.pickup_types[++num] = '\0';
1704 if (badopt) badoption(opts);
1709 * player_selection: dialog | prompts */
1710 fullname = "player_selection";
1711 if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) {
1712 op = string_for_opt(opts, negated);
1713 if (op && !negated) {
1714 if (!strncmpi (op, "dialog", sizeof("dialog")-1))
1715 iflags.wc_player_selection = VIA_DIALOG;
1716 else if (!strncmpi (op, "prompt", sizeof("prompt")-1))
1717 iflags.wc_player_selection = VIA_PROMPTS;
1720 } else if (negated) bad_negation(fullname, TRUE);
1724 /* things to disclose at end of game */
1725 if (match_optname(opts, "disclose", 7, TRUE)) {
1727 * The order that the end_disclore options are stored:
1728 * inventory, attribs, vanquished, genocided, conduct
1729 * There is an array in flags:
1730 * end_disclose[NUM_DISCLOSURE_OPT];
1731 * with option settings for the each of the following:
1732 * iagvc [see disclosure_options in decl.c]:
1733 * Legal setting values in that array are:
1734 * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes
1735 * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no
1736 * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask
1737 * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask
1739 * Those setting values can be used in the option
1740 * string as a prefix to get the desired behaviour.
1742 * For backward compatibility, no prefix is required,
1743 * and the presence of a i,a,g,v, or c without a prefix
1744 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
1746 boolean badopt = FALSE;
1747 int idx, prefix_val;
1749 op = string_for_opt(opts, TRUE);
1750 if (op && negated) {
1751 bad_negation("disclose", TRUE);
1754 /* "disclose" without a value means "all with prompting"
1755 and negated means "none without prompting" */
1756 if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
1757 if (op && !strcmpi(op, "none")) negated = TRUE;
1758 for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
1759 flags.end_disclose[num] = negated ?
1760 DISCLOSE_NO_WITHOUT_PROMPT :
1761 DISCLOSE_PROMPT_DEFAULT_YES;
1767 while (*op && num < sizeof flags.end_disclose - 1) {
1768 register char c, *dop;
1769 static char valid_settings[] = {
1770 DISCLOSE_PROMPT_DEFAULT_YES,
1771 DISCLOSE_PROMPT_DEFAULT_NO,
1772 DISCLOSE_YES_WITHOUT_PROMPT,
1773 DISCLOSE_NO_WITHOUT_PROMPT,
1777 if (c == 'k') c = 'v'; /* killed -> vanquished */
1778 dop = index(disclosure_options, c);
1780 idx = dop - disclosure_options;
1781 if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
1782 impossible("bad disclosure index %d %c",
1786 if (prefix_val != -1) {
1787 flags.end_disclose[idx] = prefix_val;
1790 flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
1791 } else if (index(valid_settings, c)) {
1793 } else if (c == ' ') {
1799 if (badopt) badoption(opts);
1803 /* scores:5t[op] 5a[round] o[wn] */
1804 if (match_optname(opts, "scores", 4, TRUE)) {
1806 bad_negation("scores", FALSE);
1809 if (!(op = string_for_opt(opts, FALSE))) return;
1816 while (digit(*op)) op++;
1817 } else if (*op == '!') {
1821 while (*op == ' ') op++;
1825 case 'T': flags.end_top = inum;
1828 case 'A': flags.end_around = inum;
1831 case 'O': flags.end_own = !negated;
1833 default: badoption(opts);
1836 while (letter(*++op) || *op == ' ') continue;
1837 if (*op == '/') op++;
1842 fullname = "suppress_alert";
1843 if (match_optname(opts, fullname, 4, TRUE)) {
1844 op = string_for_opt(opts, negated);
1845 if (negated) bad_negation(fullname, FALSE);
1846 else if (op) (void) feature_alert_opts(op,fullname);
1851 /* videocolors:string */
1852 fullname = "videocolors";
1853 if (match_optname(opts, fullname, 6, TRUE) ||
1854 match_optname(opts, "videocolours", 10, TRUE)) {
1856 bad_negation(fullname, FALSE);
1859 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1862 if (!assign_videocolors(opts))
1866 /* videoshades:string */
1867 fullname = "videoshades";
1868 if (match_optname(opts, fullname, 6, TRUE)) {
1870 bad_negation(fullname, FALSE);
1873 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1876 if (!assign_videoshades(opts))
1880 #endif /* VIDEOSHADES */
1883 /* video:string -- must be after longer tests */
1885 if (match_optname(opts, fullname, 5, TRUE)) {
1887 bad_negation(fullname, FALSE);
1890 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1893 if (!assign_video(opts))
1897 # endif /* NO_TERMS */
1898 /* soundcard:string -- careful not to match boolean 'sound' */
1899 fullname = "soundcard";
1900 if (match_optname(opts, fullname, 6, TRUE)) {
1902 bad_negation(fullname, FALSE);
1905 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
1908 if (!assign_soundcard(opts))
1915 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12|
1916 ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */
1917 fullname = "map_mode";
1918 if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) {
1919 op = string_for_opt(opts, negated);
1920 if (op && !negated) {
1921 if (!strncmpi (op, "tiles", sizeof("tiles")-1))
1922 iflags.wc_map_mode = MAP_MODE_TILES;
1923 else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1))
1924 iflags.wc_map_mode = MAP_MODE_ASCII4x6;
1925 else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1))
1926 iflags.wc_map_mode = MAP_MODE_ASCII6x8;
1927 else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1))
1928 iflags.wc_map_mode = MAP_MODE_ASCII8x8;
1929 else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1))
1930 iflags.wc_map_mode = MAP_MODE_ASCII16x8;
1931 else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1))
1932 iflags.wc_map_mode = MAP_MODE_ASCII7x12;
1933 else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1))
1934 iflags.wc_map_mode = MAP_MODE_ASCII8x12;
1935 else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1))
1936 iflags.wc_map_mode = MAP_MODE_ASCII16x12;
1937 else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1))
1938 iflags.wc_map_mode = MAP_MODE_ASCII12x16;
1939 else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1))
1940 iflags.wc_map_mode = MAP_MODE_ASCII10x18;
1941 else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1))
1942 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
1945 } else if (negated) bad_negation(fullname, TRUE);
1949 * scroll_amount:nn */
1950 fullname = "scroll_amount";
1951 if (match_optname(opts, fullname, sizeof("scroll_amount")-1, TRUE)) {
1952 op = string_for_opt(opts, negated);
1953 if ((negated && !op) || (!negated && op)) {
1954 iflags.wc_scroll_amount = negated ? 1 : atoi(op);
1955 } else if (negated) bad_negation(fullname, TRUE);
1959 * scroll_margin:nn */
1960 fullname = "scroll_margin";
1961 if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) {
1962 op = string_for_opt(opts, negated);
1963 if ((negated && !op) || (!negated && op)) {
1964 iflags.wc_scroll_margin = negated ? 5 : atoi(op);
1965 } else if (negated) bad_negation(fullname, TRUE);
1968 fullname = "subkeyvalue";
1969 if (match_optname(opts, fullname, 5, TRUE)) {
1970 if (negated) bad_negation(fullname, FALSE);
1972 #if defined(WIN32CON)
1973 op = string_for_opt(opts, 0);
1974 map_subkeyvalue(op);
1981 fullname = "tile_width";
1982 if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) {
1983 op = string_for_opt(opts, negated);
1984 if ((negated && !op) || (!negated && op)) {
1985 iflags.wc_tile_width = negated ? 0 : atoi(op);
1986 } else if (negated) bad_negation(fullname, TRUE);
1991 fullname = "tile_file";
1992 if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) {
1993 if ((op = string_for_opt(opts, FALSE)) != 0) {
1994 if (iflags.wc_tile_file) free(iflags.wc_tile_file);
1995 iflags.wc_tile_file = (char *)alloc(strlen(op) + 1);
1996 Strcpy(iflags.wc_tile_file, op);
2002 fullname = "tile_height";
2003 if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) {
2004 op = string_for_opt(opts, negated);
2005 if ((negated && !op) || (!negated && op)) {
2006 iflags.wc_tile_height = negated ? 0 : atoi(op);
2007 } else if (negated) bad_negation(fullname, TRUE);
2011 * vary_msgcount:nn */
2012 fullname = "vary_msgcount";
2013 if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) {
2014 op = string_for_opt(opts, negated);
2015 if ((negated && !op) || (!negated && op)) {
2016 iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
2017 } else if (negated) bad_negation(fullname, TRUE);
2020 fullname = "windowtype";
2021 if (match_optname(opts, fullname, 3, TRUE)) {
2023 bad_negation(fullname, FALSE);
2025 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2026 char buf[WINTYPELEN];
2027 nmcpy(buf, op, WINTYPELEN);
2028 choose_windows(buf);
2034 * setting window colors
2035 * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
2037 fullname = "windowcolors";
2038 if (match_optname(opts, fullname, 7, TRUE)) {
2039 if ((op = string_for_opt(opts, FALSE)) != 0) {
2040 if (!wc_set_window_colors(op))
2042 } else if (negated) bad_negation(fullname, TRUE);
2046 /* menustyle:traditional or combo or full or partial */
2047 if (match_optname(opts, "menustyle", 4, TRUE)) {
2049 boolean val_required = (strlen(opts) > 5 && !negated);
2051 if (!(op = string_for_opt(opts, !val_required))) {
2052 if (val_required) return; /* string_for_opt gave feedback */
2053 tmp = negated ? 'n' : 'f';
2058 case 'n': /* none */
2059 case 't': /* traditional */
2060 flags.menu_style = MENU_TRADITIONAL;
2062 case 'c': /* combo: trad.class sel+menu */
2063 flags.menu_style = MENU_COMBINATION;
2065 case 'p': /* partial: no class menu */
2066 flags.menu_style = MENU_PARTIAL;
2068 case 'f': /* full: class menu + menu */
2069 flags.menu_style = MENU_FULL;
2077 fullname = "menu_headings";
2078 if (match_optname(opts, fullname, 12, TRUE)) {
2080 bad_negation(fullname, FALSE);
2083 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2086 if (!strcmpi(opts,"bold"))
2087 iflags.menu_headings = ATR_BOLD;
2088 else if (!strcmpi(opts,"inverse"))
2089 iflags.menu_headings = ATR_INVERSE;
2090 else if (!strcmpi(opts,"underline"))
2091 iflags.menu_headings = ATR_ULINE;
2097 /* check for menu command mapping */
2098 for (i = 0; i < NUM_MENU_CMDS; i++) {
2099 fullname = default_menu_cmd_info[i].name;
2100 if (match_optname(opts, fullname, (int)strlen(fullname), TRUE)) {
2102 bad_negation(fullname, FALSE);
2103 else if ((op = string_for_opt(opts, FALSE)) != 0) {
2105 char c, op_buf[BUFSZ];
2106 boolean isbad = FALSE;
2108 escapes(op, op_buf);
2111 if (c == 0 || c == '\r' || c == '\n' || c == '\033' ||
2112 c == ' ' || digit(c) || (letter(c) && c != '@'))
2114 else /* reject default object class symbols */
2115 for (j = 1; j < MAXOCLASSES; j++)
2116 if (c == def_oc_syms[i]) {
2124 add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
2130 /* OK, if we still haven't recognized the option, check the boolean
2133 for (i = 0; boolopt[i].name; i++) {
2134 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
2135 /* options that don't exist */
2136 if (!boolopt[i].addr) {
2137 if (!initial && !negated)
2138 pline_The("\"%s\" option is not available.",
2142 /* options that must come from config file */
2143 if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
2144 rejectoption(boolopt[i].name);
2148 *(boolopt[i].addr) = !negated;
2150 duplicate_opt_detection(boolopt[i].name, 0);
2152 #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV)
2155 || (boolopt[i].addr) == &iflags.DECgraphics
2158 || (boolopt[i].addr) == &iflags.IBMgraphics
2160 # ifdef MAC_GRAPHICS_ENV
2161 || (boolopt[i].addr) == &iflags.MACgraphics
2164 # ifdef REINCARNATION
2165 if (!initial && Is_rogue_level(&u.uz))
2166 assign_rogue_graphics(FALSE);
2170 if ((boolopt[i].addr) == &iflags.DECgraphics)
2171 switch_graphics(iflags.DECgraphics ?
2172 DEC_GRAPHICS : ASCII_GRAPHICS);
2175 if ((boolopt[i].addr) == &iflags.IBMgraphics)
2176 switch_graphics(iflags.IBMgraphics ?
2177 IBM_GRAPHICS : ASCII_GRAPHICS);
2179 # ifdef MAC_GRAPHICS_ENV
2180 if ((boolopt[i].addr) == &iflags.MACgraphics)
2181 switch_graphics(iflags.MACgraphics ?
2182 MAC_GRAPHICS : ASCII_GRAPHICS);
2184 # ifdef REINCARNATION
2185 if (!initial && Is_rogue_level(&u.uz))
2186 assign_rogue_graphics(TRUE);
2189 #endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */
2191 /* only do processing below if setting with doset() */
2192 if (initial) return;
2194 if ((boolopt[i].addr) == &flags.time
2196 || (boolopt[i].addr) == &flags.showexp
2198 #ifdef SCORE_ON_BOTL
2199 || (boolopt[i].addr) == &flags.showscore
2204 else if ((boolopt[i].addr) == &flags.invlet_constant) {
2205 if (flags.invlet_constant) reassign();
2208 else if ((boolopt[i].addr) == &flags.biff) {
2209 if (flags.biff) lan_mail_init();
2210 else lan_mail_finish();
2213 else if ((boolopt[i].addr) == &flags.lit_corridor) {
2215 * All corridor squares seen via night vision or
2216 * candles & lamps change. Update them by calling
2217 * newsym() on them. Don't do this if we are
2218 * initializing the options --- the vision system
2221 vision_recalc(2); /* shut down vision */
2222 vision_full_recalc = 1; /* delayed recalc */
2224 else if ((boolopt[i].addr) == &iflags.use_inverse ||
2225 (boolopt[i].addr) == &iflags.showrace ||
2226 (boolopt[i].addr) == &iflags.hilite_pet) {
2230 else if ((boolopt[i].addr) == &iflags.use_color) {
2233 if ((boolopt[i].addr) == &iflags.use_color
2248 /* out of valid options */
2253 static NEARDATA const char *menutype[] = {
2254 "traditional", "combination", "partial", "full"
2257 static NEARDATA const char *burdentype[] = {
2258 "unencumbered", "burdened", "stressed",
2259 "strained", "overtaxed", "overloaded"
2262 static NEARDATA const char *runmodes[] = {
2263 "teleport", "run", "walk", "crawl"
2267 * Convert the given string of object classes to a string of default object
2276 while ((i = (int) *src++) != 0) {
2277 if (i < 0 || i >= MAXOCLASSES)
2278 impossible("oc_to_str: illegal object class %d", i);
2280 *dest++ = def_oc_syms[i];
2286 * Add the given mapping to the menu command map list. Always keep the
2287 * maps valid C strings.
2290 add_menu_cmd_alias(from_ch, to_ch)
2291 char from_ch, to_ch;
2293 if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS)
2294 pline("out of menu map space.");
2296 mapped_menu_cmds[n_menu_mapped] = from_ch;
2297 mapped_menu_op[n_menu_mapped] = to_ch;
2299 mapped_menu_cmds[n_menu_mapped] = 0;
2300 mapped_menu_op[n_menu_mapped] = 0;
2305 * Map the given character to its corresponding menu command. If it
2306 * doesn't match anything, just return the original.
2312 char *found = index(mapped_menu_cmds, ch);
2314 int idx = found - mapped_menu_cmds;
2315 ch = mapped_menu_op[idx];
2321 #if defined(MICRO) || defined(MAC) || defined(WIN32)
2322 # define OPTIONS_HEADING "OPTIONS"
2324 # define OPTIONS_HEADING "NETHACKOPTIONS"
2327 static char fmtstr_doset_add_menu[] = "%s%-15s [%s] ";
2328 static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
2331 doset_add_menu(win, option, indexoffset)
2332 winid win; /* window to add to */
2333 const char *option; /* option name */
2334 int indexoffset; /* value to add to index in compopt[], or zero
2335 if option cannot be changed */
2337 const char *value = "unknown"; /* current value */
2338 char buf[BUFSZ], buf2[BUFSZ];
2343 if (indexoffset == 0) {
2345 value = get_compopt_value(option, buf2);
2347 for (i=0; compopt[i].name; i++)
2348 if (strcmp(option, compopt[i].name) == 0) break;
2350 if (compopt[i].name) {
2351 any.a_int = i + 1 + indexoffset;
2352 value = get_compopt_value(option, buf2);
2354 /* We are trying to add an option not found in compopt[].
2355 This is almost certainly bad, but we'll let it through anyway
2356 (with a zero value, so it can't be selected). */
2360 /* " " replaces "a - " -- assumes menus follow that style */
2361 if (!iflags.menu_tab_sep)
2362 Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", option, value);
2364 Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
2365 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
2368 /* Changing options via menu by Per Liboriussen */
2372 char buf[BUFSZ], buf2[BUFSZ];
2373 int i, pass, boolcount, pick_cnt, pick_idx, opt_indx;
2377 menu_item *pick_list;
2378 int indexoffset, startpass, endpass;
2379 boolean setinitial = FALSE, fromfile = FALSE;
2380 int biggest_name = 0;
2382 tmpwin = create_nhwindow(NHW_MENU);
2386 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2387 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
2389 /* first list any other non-modifiable booleans, then modifiable ones */
2390 for (pass = 0; pass <= 1; pass++)
2391 for (i = 0; boolopt[i].name; i++)
2392 if ((bool_p = boolopt[i].addr) != 0 &&
2393 ((boolopt[i].optflags == DISP_IN_GAME && pass == 0) ||
2394 (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
2395 if (bool_p == &flags.female) continue; /* obsolete */
2397 if (bool_p == &iflags.sanity_check && !wizard) continue;
2398 if (bool_p == &iflags.menu_tab_sep && !wizard) continue;
2400 if (is_wc_option(boolopt[i].name) &&
2401 !wc_supported(boolopt[i].name)) continue;
2402 if (is_wc2_option(boolopt[i].name) &&
2403 !wc2_supported(boolopt[i].name)) continue;
2404 any.a_int = (pass == 0) ? 0 : i + 1;
2405 if (!iflags.menu_tab_sep)
2406 Sprintf(buf, "%s%-13s [%s]",
2407 pass == 0 ? " " : "",
2408 boolopt[i].name, *bool_p ? "true" : "false");
2410 Sprintf(buf, "%s\t[%s]",
2411 boolopt[i].name, *bool_p ? "true" : "false");
2412 add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
2413 ATR_NONE, buf, MENU_UNSELECTED);
2417 indexoffset = boolcount;
2419 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2420 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2421 "Compounds (selecting will prompt for new value):",
2424 startpass = DISP_IN_GAME;
2425 endpass = SET_IN_GAME;
2427 /* spin through the options to find the biggest name
2428 and adjust the format string accordingly if needed */
2430 for (i = 0; compopt[i].name; i++)
2431 if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass &&
2432 strlen(compopt[i].name) > (unsigned) biggest_name)
2433 biggest_name = (int) strlen(compopt[i].name);
2434 if (biggest_name > 30) biggest_name = 30;
2435 if (!iflags.menu_tab_sep)
2436 Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
2438 /* deliberately put `name', `role', `race', `gender' first */
2439 doset_add_menu(tmpwin, "name", 0);
2440 doset_add_menu(tmpwin, "role", 0);
2441 doset_add_menu(tmpwin, "race", 0);
2442 doset_add_menu(tmpwin, "gender", 0);
2444 for (pass = startpass; pass <= endpass; pass++)
2445 for (i = 0; compopt[i].name; i++)
2446 if (compopt[i].optflags == pass) {
2447 if (!strcmp(compopt[i].name, "name") ||
2448 !strcmp(compopt[i].name, "role") ||
2449 !strcmp(compopt[i].name, "race") ||
2450 !strcmp(compopt[i].name, "gender"))
2452 else if (is_wc_option(compopt[i].name) &&
2453 !wc_supported(compopt[i].name))
2455 else if (is_wc2_option(compopt[i].name) &&
2456 !wc2_supported(compopt[i].name))
2459 doset_add_menu(tmpwin, compopt[i].name,
2460 (pass == DISP_IN_GAME) ? 0 : indexoffset);
2462 #ifdef AUTOPICKUP_EXCEPTIONS
2464 Sprintf(buf, "autopickup exceptions (%d currently set)",
2465 count_ape_maps((int *)0, (int *)0));
2466 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
2468 #endif /* AUTOPICKUP_EXCEPTIONS */
2469 #ifdef PREFIXES_IN_USE
2471 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2472 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2473 "Variable playground locations:", MENU_UNSELECTED);
2474 for (i = 0; i < PREFIX_COUNT; i++)
2475 doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
2477 end_menu(tmpwin, "Set what options?");
2478 need_redraw = FALSE;
2479 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
2481 * Walk down the selection list and either invert the booleans
2482 * or prompt for new values. In most cases, call parseoptions()
2483 * to take care of options that require special attention, like
2486 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2487 opt_indx = pick_list[pick_idx].item.a_int - 1;
2488 #ifdef AUTOPICKUP_EXCEPTIONS
2489 if (opt_indx == -2) {
2490 special_handling("autopickup_exception",
2491 setinitial, fromfile);
2494 if (opt_indx < boolcount) {
2495 /* boolean option */
2496 Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
2497 boolopt[opt_indx].name);
2498 parseoptions(buf, setinitial, fromfile);
2499 if (wc_supported(boolopt[opt_indx].name) ||
2500 wc2_supported(boolopt[opt_indx].name))
2501 preference_update(boolopt[opt_indx].name);
2503 /* compound option */
2504 opt_indx -= boolcount;
2506 if (!special_handling(compopt[opt_indx].name,
2507 setinitial, fromfile)) {
2508 Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
2510 if (buf2[0] == '\033')
2512 Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
2514 parseoptions(buf, setinitial, fromfile);
2516 if (wc_supported(compopt[opt_indx].name) ||
2517 wc2_supported(compopt[opt_indx].name))
2518 preference_update(compopt[opt_indx].name);
2521 free((genericptr_t)pick_list);
2522 pick_list = (menu_item *)0;
2525 destroy_nhwindow(tmpwin);
2532 special_handling(optname, setinitial, setfromfile)
2533 const char *optname;
2534 boolean setinitial,setfromfile;
2540 boolean retval = FALSE;
2542 /* Special handling of menustyle, pickup_burden, pickup_types,
2543 * disclose, runmode, msg_window, menu_headings, and number_pad options.
2544 #ifdef AUTOPICKUP_EXCEPTIONS
2545 * Also takes care of interactive autopickup_exception_handling changes.
2548 if (!strcmp("menustyle", optname)) {
2549 const char *style_name;
2550 menu_item *style_pick = (menu_item *)0;
2551 tmpwin = create_nhwindow(NHW_MENU);
2553 for (i = 0; i < SIZE(menutype); i++) {
2554 style_name = menutype[i];
2555 /* note: separate `style_name' variable used
2556 to avoid an optimizer bug in VAX C V2.3 */
2558 add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0,
2559 ATR_NONE, style_name, MENU_UNSELECTED);
2561 end_menu(tmpwin, "Select menustyle:");
2562 if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
2563 flags.menu_style = style_pick->item.a_int - 1;
2564 free((genericptr_t)style_pick);
2566 destroy_nhwindow(tmpwin);
2568 } else if (!strcmp("pickup_burden", optname)) {
2569 const char *burden_name, *burden_letters = "ubsntl";
2570 menu_item *burden_pick = (menu_item *)0;
2571 tmpwin = create_nhwindow(NHW_MENU);
2573 for (i = 0; i < SIZE(burdentype); i++) {
2574 burden_name = burdentype[i];
2576 add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0,
2577 ATR_NONE, burden_name, MENU_UNSELECTED);
2579 end_menu(tmpwin, "Select encumbrance level:");
2580 if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
2581 flags.pickup_burden = burden_pick->item.a_int - 1;
2582 free((genericptr_t)burden_pick);
2584 destroy_nhwindow(tmpwin);
2586 } else if (!strcmp("pickup_types", optname)) {
2587 /* parseoptions will prompt for the list of types */
2588 parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
2590 } else if (!strcmp("disclose", optname)) {
2591 int pick_cnt, pick_idx, opt_idx;
2592 menu_item *disclosure_category_pick = (menu_item *)0;
2594 * The order of disclose_names[]
2595 * must correspond to disclosure_options in decl.h
2597 static const char *disclosure_names[] = {
2598 "inventory", "attributes", "vanquished", "genocides", "conduct"
2600 int disc_cat[NUM_DISCLOSURE_OPTIONS];
2601 const char *disclosure_name;
2603 tmpwin = create_nhwindow(NHW_MENU);
2605 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2606 disclosure_name = disclosure_names[i];
2608 add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
2609 ATR_NONE, disclosure_name, MENU_UNSELECTED);
2612 end_menu(tmpwin, "Change which disclosure options categories:");
2613 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) {
2614 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2615 opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1;
2616 disc_cat[opt_idx] = 1;
2618 free((genericptr_t)disclosure_category_pick);
2619 disclosure_category_pick = (menu_item *)0;
2621 destroy_nhwindow(tmpwin);
2623 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2626 menu_item *disclosure_option_pick = (menu_item *)0;
2627 Sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]);
2628 tmpwin = create_nhwindow(NHW_MENU);
2630 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
2631 add_menu(tmpwin, NO_GLYPH, &any, 'a', 0,
2632 ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED);
2634 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
2635 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
2636 ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED);
2638 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
2639 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
2640 ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED);
2642 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
2643 add_menu(tmpwin, NO_GLYPH, &any, 'd', 0,
2644 ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED);
2645 end_menu(tmpwin, dbuf);
2646 if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) {
2647 flags.end_disclose[i] = disclosure_option_pick->item.a_char;
2648 free((genericptr_t)disclosure_option_pick);
2650 destroy_nhwindow(tmpwin);
2654 } else if (!strcmp("runmode", optname)) {
2655 const char *mode_name;
2656 menu_item *mode_pick = (menu_item *)0;
2657 tmpwin = create_nhwindow(NHW_MENU);
2659 for (i = 0; i < SIZE(runmodes); i++) {
2660 mode_name = runmodes[i];
2662 add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0,
2663 ATR_NONE, mode_name, MENU_UNSELECTED);
2665 end_menu(tmpwin, "Select run/travel display mode:");
2666 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
2667 iflags.runmode = mode_pick->item.a_int - 1;
2668 free((genericptr_t)mode_pick);
2670 destroy_nhwindow(tmpwin);
2674 else if (!strcmp("msg_window", optname)) {
2675 /* by Christian W. Cooper */
2676 menu_item *window_pick = (menu_item *)0;
2677 tmpwin = create_nhwindow(NHW_MENU);
2680 add_menu(tmpwin, NO_GLYPH, &any, 's', 0,
2681 ATR_NONE, "single", MENU_UNSELECTED);
2683 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
2684 ATR_NONE, "combination", MENU_UNSELECTED);
2686 add_menu(tmpwin, NO_GLYPH, &any, 'f', 0,
2687 ATR_NONE, "full", MENU_UNSELECTED);
2689 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
2690 ATR_NONE, "reversed", MENU_UNSELECTED);
2691 end_menu(tmpwin, "Select message history display type:");
2692 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
2693 iflags.prevmsg_window = window_pick->item.a_char;
2694 free((genericptr_t)window_pick);
2696 destroy_nhwindow(tmpwin);
2700 else if (!strcmp("align_message", optname) ||
2701 !strcmp("align_status", optname)) {
2702 menu_item *window_pick = (menu_item *)0;
2704 boolean msg = (*(optname+6) == 'm');
2706 tmpwin = create_nhwindow(NHW_MENU);
2708 any.a_int = ALIGN_TOP;
2709 add_menu(tmpwin, NO_GLYPH, &any, 't', 0,
2710 ATR_NONE, "top", MENU_UNSELECTED);
2711 any.a_int = ALIGN_BOTTOM;
2712 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
2713 ATR_NONE, "bottom", MENU_UNSELECTED);
2714 any.a_int = ALIGN_LEFT;
2715 add_menu(tmpwin, NO_GLYPH, &any, 'l', 0,
2716 ATR_NONE, "left", MENU_UNSELECTED);
2717 any.a_int = ALIGN_RIGHT;
2718 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
2719 ATR_NONE, "right", MENU_UNSELECTED);
2720 Sprintf(abuf, "Select %s window placement relative to the map:",
2721 msg ? "message" : "status");
2722 end_menu(tmpwin, abuf);
2723 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
2724 if (msg) iflags.wc_align_message = window_pick->item.a_int;
2725 else iflags.wc_align_status = window_pick->item.a_int;
2726 free((genericptr_t)window_pick);
2728 destroy_nhwindow(tmpwin);
2730 } else if (!strcmp("number_pad", optname)) {
2731 static const char *npchoices[3] =
2732 {"0 (off)", "1 (on)", "2 (on, DOS compatible)"};
2733 const char *npletters = "abc";
2734 menu_item *mode_pick = (menu_item *)0;
2736 tmpwin = create_nhwindow(NHW_MENU);
2738 for (i = 0; i < SIZE(npchoices); i++) {
2740 add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
2741 ATR_NONE, npchoices[i], MENU_UNSELECTED);
2743 end_menu(tmpwin, "Select number_pad mode:");
2744 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
2745 int mode = mode_pick->item.a_int - 1;
2749 iflags.num_pad_mode = 1;
2753 iflags.num_pad_mode = 0;
2758 iflags.num_pad_mode = 0;
2760 free((genericptr_t)mode_pick);
2762 destroy_nhwindow(tmpwin);
2764 } else if (!strcmp("menu_headings", optname)) {
2765 static const char *mhchoices[3] = {"bold", "inverse", "underline"};
2766 const char *npletters = "biu";
2767 menu_item *mode_pick = (menu_item *)0;
2769 tmpwin = create_nhwindow(NHW_MENU);
2771 for (i = 0; i < SIZE(mhchoices); i++) {
2773 add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
2774 ATR_NONE, mhchoices[i], MENU_UNSELECTED);
2776 end_menu(tmpwin, "How to highlight menu headings:");
2777 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
2778 int mode = mode_pick->item.a_int - 1;
2781 iflags.menu_headings = ATR_ULINE;
2784 iflags.menu_headings = ATR_BOLD;
2788 iflags.menu_headings = ATR_INVERSE;
2790 free((genericptr_t)mode_pick);
2792 destroy_nhwindow(tmpwin);
2794 #ifdef AUTOPICKUP_EXCEPTIONS
2795 } else if (!strcmp("autopickup_exception", optname)) {
2797 int pick_cnt, pick_idx, opt_idx, pass;
2798 int totalapes = 0, numapes[2] = {0,0};
2799 menu_item *pick_list = (menu_item *)0;
2802 struct autopickup_exception *ape;
2803 static const char *action_titles[] = {
2804 "a", "add new autopickup exception",
2805 "l", "list autopickup exceptions",
2806 "r", "remove existing autopickup exception",
2807 "e", "exit this menu",
2811 totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
2812 tmpwin = create_nhwindow(NHW_MENU);
2815 for (i = 0; i < SIZE(action_titles) ; i += 2) {
2817 if (!totalapes && (i >= 2 && i < 6)) continue;
2818 add_menu(tmpwin, NO_GLYPH, &any, *action_titles[i],
2819 0, ATR_NONE, action_titles[i+1], MENU_UNSELECTED);
2821 end_menu(tmpwin, "Do what?");
2822 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
2823 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
2824 opt_idx = pick_list[pick_idx].item.a_int - 1;
2826 free((genericptr_t)pick_list);
2827 pick_list = (menu_item *)0;
2829 destroy_nhwindow(tmpwin);
2830 if (pick_cnt < 1) return FALSE;
2832 if (opt_idx == 0) { /* add new */
2833 getlin("What new autopickup exception pattern?", &apebuf[1]);
2834 if (apebuf[1] == '\033') return FALSE;
2836 Strcat(apebuf,"\"");
2837 add_autopickup_exception(apebuf);
2839 } else if (opt_idx == 3) {
2841 } else { /* remove */
2842 tmpwin = create_nhwindow(NHW_MENU);
2844 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
2845 if (numapes[pass] == 0) continue;
2846 ape = iflags.autopickup_exceptions[pass];
2848 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2849 (pass == 0) ? "Never pickup" : "Always pickup",
2851 for (i = 0; i < numapes[pass] && ape; i++) {
2852 any.a_void = (opt_idx == 1) ? 0 : ape;
2853 Sprintf(apebuf, "\"%s\"", ape->pattern);
2854 add_menu(tmpwin, NO_GLYPH, &any,
2855 0, 0, ATR_NONE, apebuf, MENU_UNSELECTED);
2859 Sprintf(apebuf, "%s autopickup exceptions",
2860 (opt_idx == 1) ? "List of" : "Remove which");
2861 end_menu(tmpwin, apebuf);
2862 pick_cnt = select_menu(tmpwin,
2863 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
2866 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
2867 remove_autopickup_exception(
2868 (struct autopickup_exception *)pick_list[pick_idx].item.a_void);
2870 free((genericptr_t)pick_list);
2871 pick_list = (menu_item *)0;
2872 destroy_nhwindow(tmpwin);
2876 #endif /* AUTOPICKUP_EXCEPTIONS */
2881 #define rolestring(val,array,field) ((val >= 0) ? array[val].field : \
2882 (val == ROLE_RANDOM) ? randomrole : none)
2884 /* This is ugly. We have all the option names in the compopt[] array,
2885 but we need to look at each option individually to get the value. */
2886 STATIC_OVL const char *
2887 get_compopt_value(optname, buf)
2888 const char *optname;
2891 char ocl[MAXOCLASSES+1];
2892 static const char none[] = "(none)", randomrole[] = "random",
2893 to_be_done[] = "(to be done)",
2894 defopt[] = "default",
2899 if (!strcmp(optname,"align_message"))
2900 Sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP ? "top" :
2901 iflags.wc_align_message == ALIGN_LEFT ? "left" :
2902 iflags.wc_align_message == ALIGN_BOTTOM ? "bottom" :
2903 iflags.wc_align_message == ALIGN_RIGHT ? "right" :
2905 else if (!strcmp(optname,"align_status"))
2906 Sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP ? "top" :
2907 iflags.wc_align_status == ALIGN_LEFT ? "left" :
2908 iflags.wc_align_status == ALIGN_BOTTOM ? "bottom" :
2909 iflags.wc_align_status == ALIGN_RIGHT ? "right" :
2911 else if (!strcmp(optname,"align"))
2912 Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
2914 else if (!strcmp(optname,"altkeyhandler"))
2915 Sprintf(buf, "%s", iflags.altkeyhandler[0] ?
2916 iflags.altkeyhandler : "default");
2918 else if (!strcmp(optname, "boulder"))
2919 Sprintf(buf, "%c", iflags.bouldersym ?
2920 iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]);
2921 else if (!strcmp(optname, "catname"))
2922 Sprintf(buf, "%s", catname[0] ? catname : none );
2923 else if (!strcmp(optname, "disclose")) {
2924 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
2926 if (i) Strcat(buf," ");
2928 topt[0] = flags.end_disclose[i];
2930 topt[0] = disclosure_options[i];
2934 else if (!strcmp(optname, "dogname"))
2935 Sprintf(buf, "%s", dogname[0] ? dogname : none );
2936 else if (!strcmp(optname, "dungeon"))
2937 Sprintf(buf, "%s", to_be_done);
2938 else if (!strcmp(optname, "effects"))
2939 Sprintf(buf, "%s", to_be_done);
2940 else if (!strcmp(optname, "font_map"))
2941 Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
2942 else if (!strcmp(optname, "font_message"))
2943 Sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt);
2944 else if (!strcmp(optname, "font_status"))
2945 Sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt);
2946 else if (!strcmp(optname, "font_menu"))
2947 Sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
2948 else if (!strcmp(optname, "font_text"))
2949 Sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt);
2950 else if (!strcmp(optname, "font_size_map")) {
2951 if (iflags.wc_fontsiz_map) Sprintf(buf, "%d", iflags.wc_fontsiz_map);
2952 else Strcpy(buf, defopt);
2954 else if (!strcmp(optname, "font_size_message")) {
2955 if (iflags.wc_fontsiz_message) Sprintf(buf, "%d",
2956 iflags.wc_fontsiz_message);
2957 else Strcpy(buf, defopt);
2959 else if (!strcmp(optname, "font_size_status")) {
2960 if (iflags.wc_fontsiz_status) Sprintf(buf, "%d", iflags.wc_fontsiz_status);
2961 else Strcpy(buf, defopt);
2963 else if (!strcmp(optname, "font_size_menu")) {
2964 if (iflags.wc_fontsiz_menu) Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
2965 else Strcpy(buf, defopt);
2967 else if (!strcmp(optname, "font_size_text")) {
2968 if (iflags.wc_fontsiz_text) Sprintf(buf, "%d",iflags.wc_fontsiz_text);
2969 else Strcpy(buf, defopt);
2971 else if (!strcmp(optname, "fruit"))
2972 Sprintf(buf, "%s", pl_fruit);
2973 else if (!strcmp(optname, "gender"))
2974 Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
2975 else if (!strcmp(optname, "horsename"))
2976 Sprintf(buf, "%s", horsename[0] ? horsename : none);
2977 else if (!strcmp(optname, "map_mode"))
2979 iflags.wc_map_mode == MAP_MODE_TILES ? "tiles" :
2980 iflags.wc_map_mode == MAP_MODE_ASCII4x6 ? "ascii4x6" :
2981 iflags.wc_map_mode == MAP_MODE_ASCII6x8 ? "ascii6x8" :
2982 iflags.wc_map_mode == MAP_MODE_ASCII8x8 ? "ascii8x8" :
2983 iflags.wc_map_mode == MAP_MODE_ASCII16x8 ? "ascii16x8" :
2984 iflags.wc_map_mode == MAP_MODE_ASCII7x12 ? "ascii7x12" :
2985 iflags.wc_map_mode == MAP_MODE_ASCII8x12 ? "ascii8x12" :
2986 iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" :
2987 iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" :
2988 iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" :
2989 iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ?
2990 "fit_to_screen" : defopt);
2991 else if (!strcmp(optname, "menustyle"))
2992 Sprintf(buf, "%s", menutype[(int)flags.menu_style] );
2993 else if (!strcmp(optname, "menu_deselect_all"))
2994 Sprintf(buf, "%s", to_be_done);
2995 else if (!strcmp(optname, "menu_deselect_page"))
2996 Sprintf(buf, "%s", to_be_done);
2997 else if (!strcmp(optname, "menu_first_page"))
2998 Sprintf(buf, "%s", to_be_done);
2999 else if (!strcmp(optname, "menu_invert_all"))
3000 Sprintf(buf, "%s", to_be_done);
3001 else if (!strcmp(optname, "menu_headings")) {
3002 Sprintf(buf, "%s", (iflags.menu_headings == ATR_BOLD) ?
3003 "bold" : (iflags.menu_headings == ATR_INVERSE) ?
3004 "inverse" : (iflags.menu_headings == ATR_ULINE) ?
3005 "underline" : "unknown");
3007 else if (!strcmp(optname, "menu_invert_page"))
3008 Sprintf(buf, "%s", to_be_done);
3009 else if (!strcmp(optname, "menu_last_page"))
3010 Sprintf(buf, "%s", to_be_done);
3011 else if (!strcmp(optname, "menu_next_page"))
3012 Sprintf(buf, "%s", to_be_done);
3013 else if (!strcmp(optname, "menu_previous_page"))
3014 Sprintf(buf, "%s", to_be_done);
3015 else if (!strcmp(optname, "menu_search"))
3016 Sprintf(buf, "%s", to_be_done);
3017 else if (!strcmp(optname, "menu_select_all"))
3018 Sprintf(buf, "%s", to_be_done);
3019 else if (!strcmp(optname, "menu_select_page"))
3020 Sprintf(buf, "%s", to_be_done);
3021 else if (!strcmp(optname, "monsters"))
3022 Sprintf(buf, "%s", to_be_done);
3023 else if (!strcmp(optname, "msghistory"))
3024 Sprintf(buf, "%u", iflags.msg_history);
3026 else if (!strcmp(optname, "msg_window"))
3027 Sprintf(buf, "%s", (iflags.prevmsg_window=='s') ? "single" :
3028 (iflags.prevmsg_window=='c') ? "combination" :
3029 (iflags.prevmsg_window=='f') ? "full" : "reversed");
3031 else if (!strcmp(optname, "name"))
3032 Sprintf(buf, "%s", plname);
3033 else if (!strcmp(optname, "number_pad"))
3035 (!iflags.num_pad) ? "0=off" :
3036 (iflags.num_pad_mode) ? "2=on, DOS compatible" : "1=on");
3037 else if (!strcmp(optname, "objects"))
3038 Sprintf(buf, "%s", to_be_done);
3039 else if (!strcmp(optname, "packorder")) {
3040 oc_to_str(flags.inv_order, ocl);
3041 Sprintf(buf, "%s", ocl);
3044 else if (!strcmp(optname, "palette"))
3045 Sprintf(buf, "%s", get_color_string());
3047 else if (!strcmp(optname, "pettype"))
3048 Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" :
3049 (preferred_pet == 'd') ? "dog" :
3050 (preferred_pet == 'n') ? "none" : "random");
3051 else if (!strcmp(optname, "pickup_burden"))
3052 Sprintf(buf, "%s", burdentype[flags.pickup_burden] );
3053 else if (!strcmp(optname, "pickup_types")) {
3054 oc_to_str(flags.pickup_types, ocl);
3055 Sprintf(buf, "%s", ocl[0] ? ocl : "all" );
3057 else if (!strcmp(optname, "race"))
3058 Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
3059 else if (!strcmp(optname, "role"))
3060 Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
3061 else if (!strcmp(optname, "runmode"))
3062 Sprintf(buf, "%s", runmodes[iflags.runmode]);
3063 else if (!strcmp(optname, "scores")) {
3064 Sprintf(buf, "%d top/%d around%s", flags.end_top,
3065 flags.end_around, flags.end_own ? "/own" : "");
3067 else if (!strcmp(optname, "scroll_amount")) {
3068 if (iflags.wc_scroll_amount) Sprintf(buf, "%d",iflags.wc_scroll_amount);
3069 else Strcpy(buf, defopt);
3071 else if (!strcmp(optname, "scroll_margin")) {
3072 if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin);
3073 else Strcpy(buf, defopt);
3075 else if (!strcmp(optname, "player_selection"))
3076 Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
3078 else if (!strcmp(optname, "soundcard"))
3079 Sprintf(buf, "%s", to_be_done);
3081 else if (!strcmp(optname, "suppress_alert")) {
3082 if (flags.suppress_alert == 0L)
3085 Sprintf(buf, "%lu.%lu.%lu",
3086 FEATURE_NOTICE_VER_MAJ,
3087 FEATURE_NOTICE_VER_MIN,
3088 FEATURE_NOTICE_VER_PATCH);
3090 else if (!strcmp(optname, "tile_file"))
3091 Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
3092 else if (!strcmp(optname, "tile_height")) {
3093 if (iflags.wc_tile_height) Sprintf(buf, "%d",iflags.wc_tile_height);
3094 else Strcpy(buf, defopt);
3096 else if (!strcmp(optname, "tile_width")) {
3097 if (iflags.wc_tile_width) Sprintf(buf, "%d",iflags.wc_tile_width);
3098 else Strcpy(buf, defopt);
3100 else if (!strcmp(optname, "traps"))
3101 Sprintf(buf, "%s", to_be_done);
3102 else if (!strcmp(optname, "vary_msgcount")) {
3103 if (iflags.wc_vary_msgcount) Sprintf(buf, "%d",iflags.wc_vary_msgcount);
3104 else Strcpy(buf, defopt);
3107 else if (!strcmp(optname, "video"))
3108 Sprintf(buf, "%s", to_be_done);
3111 else if (!strcmp(optname, "videoshades"))
3112 Sprintf(buf, "%s-%s-%s", shade[0],shade[1],shade[2]);
3113 else if (!strcmp(optname, "videocolors"))
3114 Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
3115 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
3116 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
3117 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
3118 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
3119 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
3120 ttycolors[CLR_BRIGHT_MAGENTA],
3121 ttycolors[CLR_BRIGHT_CYAN]);
3122 #endif /* VIDEOSHADES */
3123 else if (!strcmp(optname, "windowtype"))
3124 Sprintf(buf, "%s", windowprocs.name);
3125 else if (!strcmp(optname, "windowcolors"))
3126 Sprintf(buf, "%s/%s %s/%s %s/%s %s/%s",
3127 iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief,
3128 iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief,
3129 iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief,
3130 iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief,
3131 iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief,
3132 iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief,
3133 iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief,
3134 iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief);
3135 #ifdef PREFIXES_IN_USE
3137 for (i = 0; i < PREFIX_COUNT; ++i)
3138 if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
3139 Sprintf(buf, "%s", fqn_prefix[i]);
3143 if (buf[0]) return buf;
3144 else return "unknown";
3150 char buf[BUFSZ], ocl[MAXOCLASSES+1];
3152 flags.pickup = !flags.pickup;
3154 oc_to_str(flags.pickup_types, ocl);
3155 Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
3156 #ifdef AUTOPICKUP_EXCEPTIONS
3157 (iflags.autopickup_exceptions[AP_LEAVE] ||
3158 iflags.autopickup_exceptions[AP_GRAB]) ?
3159 ((count_ape_maps((int *)0, (int *)0) == 1) ?
3160 ", with one exception" : ", with some exceptions") :
3166 pline("Autopickup: %s.", buf);
3170 #ifdef AUTOPICKUP_EXCEPTIONS
3172 add_autopickup_exception(mapping)
3173 const char *mapping;
3175 struct autopickup_exception *ape, **apehead;
3176 char text[256], *text2;
3178 boolean grab = FALSE;
3180 if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
3182 if (*text2 == '<') { /* force autopickup */
3185 } else if (*text2 == '>') { /* default - Do not pickup */
3189 textsize = strlen(text2);
3190 apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] :
3191 &iflags.autopickup_exceptions[AP_LEAVE];
3192 ape = (struct autopickup_exception *)
3193 alloc(sizeof(struct autopickup_exception));
3194 ape->pattern = (char *) alloc(textsize+1);
3195 Strcpy(ape->pattern, text2);
3197 if (!*apehead) ape->next = (struct autopickup_exception *)0;
3198 else ape->next = *apehead;
3201 raw_print("syntax error in AUTOPICKUP_EXCEPTION");
3208 remove_autopickup_exception(whichape)
3209 struct autopickup_exception *whichape;
3211 struct autopickup_exception *ape, *prev = 0;
3212 int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
3214 for (ape = iflags.autopickup_exceptions[chain]; ape;) {
3215 if (ape == whichape) {
3216 struct autopickup_exception *freeape = ape;
3218 if (prev) prev->next = ape;
3219 else iflags.autopickup_exceptions[chain] = ape;
3220 free(freeape->pattern);
3230 count_ape_maps(leave, grab)
3233 struct autopickup_exception *ape;
3234 int pass, totalapes, numapes[2] = {0,0};
3236 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
3237 ape = iflags.autopickup_exceptions[pass];
3243 totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
3244 if (leave) *leave = numapes[AP_LEAVE];
3245 if (grab) *grab = numapes[AP_GRAB];
3250 free_autopickup_exceptions()
3252 struct autopickup_exception *ape;
3255 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
3256 while((ape = iflags.autopickup_exceptions[pass]) != 0) {
3258 iflags.autopickup_exceptions[pass] = ape->next;
3263 #endif /* AUTOPICKUP_EXCEPTIONS */
3265 /* data for option_help() */
3266 static const char *opt_intro[] = {
3268 " NetHack Options Help:",
3270 #define CONFIG_SLOT 3 /* fill in next value at run-time */
3272 #if !defined(MICRO) && !defined(MAC)
3273 "or use `NETHACKOPTIONS=\"<options>\"' in your environment",
3275 "(<options> is a list of options separated by commas)",
3277 "-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
3279 "or press \"O\" while playing and use the menu.",
3281 "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
3285 static const char *opt_epilog[] = {
3287 "Some of the options can be set only before the game is started; those",
3288 "items will not be selectable in the 'O' command's menu.",
3295 char buf[BUFSZ], buf2[BUFSZ];
3299 datawin = create_nhwindow(NHW_TEXT);
3300 Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
3301 opt_intro[CONFIG_SLOT] = (const char *) buf;
3302 for (i = 0; opt_intro[i]; i++)
3303 putstr(datawin, 0, opt_intro[i]);
3305 /* Boolean options */
3306 for (i = 0; boolopt[i].name; i++) {
3307 if (boolopt[i].addr) {
3309 if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue;
3310 if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue;
3312 next_opt(datawin, boolopt[i].name);
3315 next_opt(datawin, "");
3317 /* Compound options */
3318 putstr(datawin, 0, "Compound options:");
3319 for (i = 0; compopt[i].name; i++) {
3320 Sprintf(buf2, "`%s'", compopt[i].name);
3321 Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
3322 compopt[i+1].name ? ',' : '.');
3323 putstr(datawin, 0, buf);
3326 for (i = 0; opt_epilog[i]; i++)
3327 putstr(datawin, 0, opt_epilog[i]);
3329 display_nhwindow(datawin, FALSE);
3330 destroy_nhwindow(datawin);
3335 * prints the next boolean option, on the same line if possible, on a new
3336 * line if not. End with next_opt("").
3339 next_opt(datawin, str)
3343 static char *buf = 0;
3347 if (!buf) *(buf = (char *)alloc(BUFSZ)) = '\0';
3351 if (s > &buf[1] && s[-2] == ',')
3352 Strcpy(s - 2, "."); /* replace last ", " */
3353 i = COLNO; /* (greater than COLNO - 2) */
3355 i = strlen(buf) + strlen(str) + 2;
3358 if (i > COLNO - 2) { /* rule of thumb */
3359 putstr(datawin, 0, buf);
3366 putstr(datawin, 0, str);
3372 /* Returns the fid of the fruit type; if that type already exists, it
3373 * returns the fid of that one; if it does not exist, it adds a new fruit
3374 * type to the chain and returns the new one.
3381 register struct fruit *f;
3382 struct fruit *lastf = 0;
3383 int highest_fruit_id = 0;
3385 boolean user_specified = (str == pl_fruit);
3386 /* if not user-specified, then it's a fruit name for a fruit on
3390 /* Note: every fruit has an id (spe for fruit objects) of at least
3393 if (user_specified) {
3394 /* disallow naming after other foods (since it'd be impossible
3395 * to tell the difference)
3398 boolean found = FALSE, numeric = FALSE;
3400 for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS;
3402 if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
3412 for(c = pl_fruit; *c >= '0' && *c <= '9'; c++)
3414 if (isspace(*c) || *c == 0) numeric = TRUE;
3416 if (found || numeric ||
3417 !strncmp(str, "cursed ", 7) ||
3418 !strncmp(str, "uncursed ", 9) ||
3419 !strncmp(str, "blessed ", 8) ||
3420 !strncmp(str, "partly eaten ", 13) ||
3421 (!strncmp(str, "tin of ", 7) &&
3422 (!strcmp(str+7, "spinach") ||
3423 name_to_mon(str+7) >= LOW_PM)) ||
3424 !strcmp(str, "empty tin") ||
3425 ((!strncmp(eos(str)-7," corpse",7) ||
3426 !strncmp(eos(str)-4, " egg",4)) &&
3427 name_to_mon(str) >= LOW_PM))
3429 Strcpy(buf, pl_fruit);
3430 Strcpy(pl_fruit, "candied ");
3431 nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
3434 for(f=ffruit; f; f = f->nextf) {
3436 if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
3437 if(!strncmp(str, f->fname, PL_FSIZ))
3440 /* if adding another fruit would overflow spe, use a random
3441 fruit instead... we've got a lot to choose from. */
3442 if (highest_fruit_id >= 127) return rnd(127);
3445 if (ffruit) lastf->nextf = f;
3447 Strcpy(f->fname, str);
3448 f->fid = highest_fruit_id;
3451 if (user_specified) current_fruit = highest_fruit_id;
3456 * This is a somewhat generic menu for taking a list of NetHack style
3457 * class choices and presenting them via a description
3458 * rather than the traditional NetHack characters.
3459 * (Benefits users whose first exposure to NetHack is via tiles).
3462 * The title at the top of the menu.
3464 * category: 0 = monster class
3468 * FALSE = PICK_ONE, TRUE = PICK_ANY
3471 * a null terminated string containing the list of choices.
3474 * a null terminated string containing the selected characters.
3476 * Returns number selected.
3479 choose_classes_menu(prompt, category, way, class_list, class_select)
3486 menu_item *pick_list = (menu_item *)0;
3492 int next_accelerator, accelerator;
3494 if (class_list == (char *)0 || class_select == (char *)0) return 0;
3496 next_accelerator = 'a';
3498 win = create_nhwindow(NHW_MENU);
3500 while (*class_list) {
3508 text = monexplain[def_char_to_monclass(*class_list)];
3509 accelerator = *class_list;
3510 Sprintf(buf, "%s", text);
3513 text = objexplain[def_char_to_objclass(*class_list)];
3514 accelerator = next_accelerator;
3515 Sprintf(buf, "%c %s", *class_list, text);
3518 impossible("choose_classes_menu: invalid category %d",
3521 if (way && *class_select) { /* Selections there already */
3522 if (index(class_select, *class_list)) {
3526 any.a_int = *class_list;
3527 add_menu(win, NO_GLYPH, &any, accelerator,
3528 category ? *class_list : 0,
3529 ATR_NONE, buf, selected);
3533 if (next_accelerator == ('z' + 1)) next_accelerator = 'A';
3534 if (next_accelerator == ('Z' + 1)) break;
3537 end_menu(win, prompt);
3538 n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
3539 destroy_nhwindow(win);
3541 for (i = 0; i < n; ++i)
3542 *class_select++ = (char)pick_list[i].item.a_int;
3543 free((genericptr_t)pick_list);
3545 } else if (n == -1) {
3546 class_select = eos(class_select);
3550 *class_select = '\0';
3554 struct wc_Opt wc_options[] = {
3555 {"ascii_map", WC_ASCII_MAP},
3556 {"color", WC_COLOR},
3557 {"eight_bit_tty", WC_EIGHT_BIT_IN},
3558 {"hilite_pet", WC_HILITE_PET},
3559 {"popup_dialog", WC_POPUP_DIALOG},
3560 {"player_selection", WC_PLAYER_SELECTION},
3561 {"preload_tiles", WC_PRELOAD_TILES},
3562 {"tiled_map", WC_TILED_MAP},
3563 {"tile_file", WC_TILE_FILE},
3564 {"tile_width", WC_TILE_WIDTH},
3565 {"tile_height", WC_TILE_HEIGHT},
3566 {"use_inverse", WC_INVERSE},
3567 {"align_message", WC_ALIGN_MESSAGE},
3568 {"align_status", WC_ALIGN_STATUS},
3569 {"font_map", WC_FONT_MAP},
3570 {"font_menu", WC_FONT_MENU},
3571 {"font_message",WC_FONT_MESSAGE},
3573 {"perm_invent",WC_PERM_INVENT},
3575 {"font_size_map", WC_FONTSIZ_MAP},
3576 {"font_size_menu", WC_FONTSIZ_MENU},
3577 {"font_size_message", WC_FONTSIZ_MESSAGE},
3578 {"font_size_status", WC_FONTSIZ_STATUS},
3579 {"font_size_text", WC_FONTSIZ_TEXT},
3580 {"font_status", WC_FONT_STATUS},
3581 {"font_text", WC_FONT_TEXT},
3582 {"map_mode", WC_MAP_MODE},
3583 {"scroll_amount", WC_SCROLL_AMOUNT},
3584 {"scroll_margin", WC_SCROLL_MARGIN},
3585 {"splash_screen", WC_SPLASH_SCREEN},
3586 {"vary_msgcount",WC_VARY_MSGCOUNT},
3587 {"windowcolors", WC_WINDOWCOLORS},
3588 {"mouse_support", WC_MOUSE_SUPPORT},
3592 struct wc_Opt wc2_options[] = {
3593 {"fullscreen", WC2_FULLSCREEN},
3594 {"softkeyboard", WC2_SOFTKEYBOARD},
3595 {"wraptext", WC2_WRAPTEXT},
3601 * If a port wants to change or ensure that the
3602 * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
3603 * correct (for controlling its display in the option menu) call
3604 * set_option_mod_status()
3605 * with the second argument of 0,2, or 3 respectively.
3608 set_option_mod_status(optnam, status)
3613 if (status < SET_IN_FILE || status > SET_IN_GAME) {
3614 impossible("set_option_mod_status: status out of range %d.",
3618 for (k = 0; boolopt[k].name; k++) {
3619 if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
3620 boolopt[k].optflags = status;
3624 for (k = 0; compopt[k].name; k++) {
3625 if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
3626 compopt[k].optflags = status;
3633 * You can set several wc_options in one call to
3634 * set_wc_option_mod_status() by setting
3635 * the appropriate bits for each option that you
3636 * are setting in the optmask argument
3638 * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME);
3641 set_wc_option_mod_status(optmask, status)
3642 unsigned long optmask;
3646 if (status < SET_IN_FILE || status > SET_IN_GAME) {
3647 impossible("set_wc_option_mod_status: status out of range %d.",
3651 while (wc_options[k].wc_name) {
3652 if (optmask & wc_options[k].wc_bit) {
3653 set_option_mod_status(wc_options[k].wc_name, status);
3660 is_wc_option(optnam)
3664 while (wc_options[k].wc_name) {
3665 if (strcmp(wc_options[k].wc_name, optnam) == 0)
3673 wc_supported(optnam)
3677 while (wc_options[k].wc_name) {
3678 if (!strcmp(wc_options[k].wc_name, optnam) &&
3679 (windowprocs.wincap & wc_options[k].wc_bit))
3688 * You can set several wc2_options in one call to
3689 * set_wc2_option_mod_status() by setting
3690 * the appropriate bits for each option that you
3691 * are setting in the optmask argument
3693 * example: set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT, SET_IN_FILE);
3697 set_wc2_option_mod_status(optmask, status)
3698 unsigned long optmask;
3702 if (status < SET_IN_FILE || status > SET_IN_GAME) {
3703 impossible("set_wc2_option_mod_status: status out of range %d.",
3707 while (wc2_options[k].wc_name) {
3708 if (optmask & wc2_options[k].wc_bit) {
3709 set_option_mod_status(wc2_options[k].wc_name, status);
3716 is_wc2_option(optnam)
3720 while (wc2_options[k].wc_name) {
3721 if (strcmp(wc2_options[k].wc_name, optnam) == 0)
3729 wc2_supported(optnam)
3733 while (wc2_options[k].wc_name) {
3734 if (!strcmp(wc2_options[k].wc_name, optnam) &&
3735 (windowprocs.wincap2 & wc2_options[k].wc_bit))
3744 wc_set_font_name(wtype, fontname)
3748 char **fn = (char **)0;
3749 if (!fontname) return;
3752 fn = &iflags.wc_font_map;
3755 fn = &iflags.wc_font_message;
3758 fn = &iflags.wc_font_text;
3761 fn = &iflags.wc_font_menu;
3764 fn = &iflags.wc_font_status;
3771 *fn = (char *)alloc(strlen(fontname) + 1);
3772 Strcpy(*fn, fontname);
3778 wc_set_window_colors(op)
3782 * menu white/black message green/yellow status white/blue text white/black
3787 char *wn, *tfg, *tbg, *newop;
3788 static const char *wnames[] = { "menu", "message", "status", "text" };
3789 static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
3790 static char **fgp[] = {
3791 &iflags.wc_foregrnd_menu,
3792 &iflags.wc_foregrnd_message,
3793 &iflags.wc_foregrnd_status,
3794 &iflags.wc_foregrnd_text
3796 static char **bgp[] = {
3797 &iflags.wc_backgrnd_menu,
3798 &iflags.wc_backgrnd_message,
3799 &iflags.wc_backgrnd_status,
3800 &iflags.wc_backgrnd_text
3804 newop = mungspaces(buf);
3805 while (newop && *newop) {
3807 wn = tfg = tbg = (char *)0;
3809 /* until first non-space in case there's leading spaces - before colorname*/
3810 while(*newop && isspace(*newop)) newop++;
3811 if (*newop) wn = newop;
3814 /* until first space - colorname*/
3815 while(*newop && !isspace(*newop)) newop++;
3816 if (*newop) *newop = '\0';
3820 /* until first non-space - before foreground*/
3821 while(*newop && isspace(*newop)) newop++;
3822 if (*newop) tfg = newop;
3825 /* until slash - foreground */
3826 while(*newop && *newop != '/') newop++;
3827 if (*newop) *newop = '\0';
3831 /* until first non-space (in case there's leading space after slash) - before background */
3832 while(*newop && isspace(*newop)) newop++;
3833 if (*newop) tbg = newop;
3836 /* until first space - background */
3837 while(*newop && !isspace(*newop)) newop++;
3838 if (*newop) *newop++ = '\0';
3840 for (j = 0; j < 4; ++j) {
3841 if (!strcmpi(wn, wnames[j]) ||
3842 !strcmpi(wn, shortnames[j])) {
3843 if (tfg && !strstri(tfg, " ")) {
3844 if (*fgp[j]) free(*fgp[j]);
3845 *fgp[j] = (char *)alloc(strlen(tfg) + 1);
3846 Strcpy(*fgp[j], tfg);
3848 if (tbg && !strstri(tbg, " ")) {
3849 if (*bgp[j]) free(*bgp[j]);
3850 *bgp[j] = (char *)alloc(strlen(tbg) + 1);
3851 Strcpy(*bgp[j], tbg);
3860 #endif /* OPTION_LISTS_ONLY */