Annotation of early-roguelike/rogue5/options.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * This file has all the code for the option command. I would rather
! 3: * this command were not necessary, but it is the only way to keep the
! 4: * wolves off of my back.
! 5: *
! 6: * @(#)options.c 4.24 (Berkeley) 05/10/83
! 7: *
! 8: * Rogue: Exploring the Dungeons of Doom
! 9: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include <stdlib.h>
! 16: #include <curses.h>
! 17: #include <ctype.h>
! 18: #include <string.h>
! 19: #include "rogue.h"
! 20:
! 21: #define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
! 22:
! 23: #define NUM_OPTS (sizeof optlist / sizeof (OPTION))
! 24:
! 25: /*
! 26: * description of an option and what to do with it
! 27: */
! 28: struct optstruct {
! 29: char *o_name; /* option name */
! 30: char *o_prompt; /* prompt for interactive entry */
! 31: void *o_opt; /* pointer to thing to set */
! 32: /* function to print value */
! 33: void (*o_putfunc)(void *opt);
! 34: /* function to get value interactively */
! 35: int (*o_getfunc)(void *opt, WINDOW *win);
! 36: };
! 37:
! 38: typedef struct optstruct OPTION;
! 39:
! 40: void pr_optname(const OPTION *op);
! 41: int allowchange(const OPTION *op);
! 42:
! 43: static const OPTION optlist[] = {
! 44: {"terse", "Terse output",
! 45: &terse, put_bool, get_bool },
! 46: {"flush", "Flush typeahead during battle",
! 47: &fight_flush, put_bool, get_bool },
! 48: {"jump", "Show position only at end of run",
! 49: &jump, put_bool, get_bool },
! 50: {"seefloor", "Show the lamp-illuminated floor",
! 51: &see_floor, put_bool, get_sf },
! 52: {"passgo", "Follow turnings in passageways",
! 53: &passgo, put_bool, get_bool },
! 54: {"tombstone", "Print out tombstone when killed",
! 55: &tombstone, put_bool, get_bool },
! 56: {"inven", "Inventory style",
! 57: &inv_type, put_inv_t, get_inv_t },
! 58: {"name", "Name",
! 59: whoami, put_str, get_str },
! 60: {"fruit", "Fruit",
! 61: fruit, put_str, get_str },
! 62: {"file", "Save file",
! 63: file_name, put_str, get_str }
! 64: };
! 65:
! 66: /*
! 67: * option:
! 68: * Print and then set options from the terminal
! 69: */
! 70:
! 71: void
! 72: option(void)
! 73: {
! 74: const OPTION *op;
! 75: int retval;
! 76:
! 77: wclear(hw);
! 78: /*
! 79: * Display current values of options
! 80: */
! 81: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 82: {
! 83: if (allowchange(op))
! 84: {
! 85: pr_optname(op);
! 86: (*op->o_putfunc)(op->o_opt);
! 87: waddch(hw, '\n');
! 88: }
! 89: }
! 90: /*
! 91: * Set values
! 92: */
! 93: wmove(hw, 0, 0);
! 94: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 95: {
! 96: if (!allowchange(op))
! 97: continue;
! 98: pr_optname(op);
! 99: retval = (*op->o_getfunc)(op->o_opt, hw);
! 100: if (retval)
! 101: {
! 102: if (retval == QUIT)
! 103: break;
! 104: #if 0
! 105: /* Support for MINUS removed until this section is rewritten. */
! 106: else if (op > optlist) { /* MINUS */
! 107: wmove(hw, (int)(op - optlist) - 1, 0);
! 108: op -= 2;
! 109: }
! 110: else /* trying to back up beyond the top */
! 111: {
! 112: putchar('\007');
! 113: wmove(hw, 0, 0);
! 114: op--;
! 115: }
! 116: #else
! 117: break;
! 118: #endif
! 119: }
! 120: }
! 121: /*
! 122: * Switch back to original screen
! 123: */
! 124: wmove(hw, LINES - 1, 0);
! 125: waddstr(hw, "--Press space to continue--");
! 126: wrefresh(hw);
! 127: wait_for(hw, ' ');
! 128: clearok(curscr, TRUE);
! 129: touchwin(stdscr);
! 130: after = FALSE;
! 131: }
! 132:
! 133: /*
! 134: * pr_optname:
! 135: * Print out the option name prompt
! 136: */
! 137:
! 138: void
! 139: pr_optname(const OPTION *op)
! 140: {
! 141: wprintw(hw, "%s (\"%s\"): ", op->o_prompt, op->o_name);
! 142: }
! 143:
! 144: /*
! 145: * put_bool
! 146: * Put out a boolean
! 147: */
! 148:
! 149: void
! 150: put_bool(void *b)
! 151: {
! 152: waddstr(hw, *(int *) b ? "True" : "False");
! 153: }
! 154:
! 155: /*
! 156: * put_str:
! 157: * Put out a string
! 158: */
! 159:
! 160: void
! 161: put_str(void *str)
! 162: {
! 163: waddstr(hw, (char *) str);
! 164: }
! 165:
! 166: /*
! 167: * put_inv_t:
! 168: * Put out an inventory type
! 169: */
! 170:
! 171: void
! 172: put_inv_t(void *ip)
! 173: {
! 174: waddstr(hw, inv_t_name[*(int *) ip]);
! 175: }
! 176:
! 177: /*
! 178: * get_bool:
! 179: * Allow changing a boolean option and print it out
! 180: */
! 181: int
! 182: get_bool(void *vp, WINDOW *win)
! 183: {
! 184: int *bp = (int *) vp;
! 185: int oy, ox;
! 186: int op_bad;
! 187:
! 188: op_bad = TRUE;
! 189: getyx(win, oy, ox);
! 190: waddstr(win, *bp ? "True" : "False");
! 191: while (op_bad)
! 192: {
! 193: wmove(win, oy, ox);
! 194: wrefresh(win);
! 195: switch (wreadchar(win))
! 196: {
! 197: case 't':
! 198: case 'T':
! 199: *bp = TRUE;
! 200: op_bad = FALSE;
! 201: break;
! 202: case 'f':
! 203: case 'F':
! 204: *bp = FALSE;
! 205: op_bad = FALSE;
! 206: break;
! 207: case '\n':
! 208: case '\r':
! 209: op_bad = FALSE;
! 210: break;
! 211: case ESCAPE:
! 212: return QUIT;
! 213: case '-':
! 214: return MINUS;
! 215: default:
! 216: wmove(win, oy, ox + 10);
! 217: waddstr(win, "(T or F)");
! 218: }
! 219: }
! 220: wmove(win, oy, ox);
! 221: waddstr(win, *bp ? "True" : "False");
! 222: waddch(win, '\n');
! 223: return NORM;
! 224: }
! 225:
! 226: /*
! 227: * get_sf:
! 228: * Change value and handle transition problems from see_floor to
! 229: * !see_floor.
! 230: */
! 231: int
! 232: get_sf(void *vp, WINDOW *win)
! 233: {
! 234: int *bp = (int *) vp;
! 235: int was_sf;
! 236: int retval;
! 237:
! 238: was_sf = see_floor;
! 239: retval = get_bool(bp, win);
! 240: if (retval == QUIT) return(QUIT);
! 241: if (was_sf != see_floor)
! 242: {
! 243: if (!see_floor) {
! 244: see_floor = TRUE;
! 245: erase_lamp(&hero, proom);
! 246: see_floor = FALSE;
! 247: }
! 248: else
! 249: look(FALSE);
! 250: }
! 251: return(NORM);
! 252: }
! 253:
! 254: /*
! 255: * get_str:
! 256: * Set a string option
! 257: */
! 258: #define MAXINP 50 /* max string to read from terminal or environment */
! 259:
! 260: int
! 261: get_str(void *vopt, WINDOW *win)
! 262: {
! 263: char *opt = (char *) vopt;
! 264: char *sp;
! 265: int oy, ox;
! 266: size_t i;
! 267: int c;
! 268: static char buf[MAXSTR];
! 269:
! 270: getyx(win, oy, ox);
! 271: wrefresh(win);
! 272: /*
! 273: * loop reading in the string, and put it in a temporary buffer
! 274: */
! 275: for (sp = buf; (c = wreadchar(win)) != '\n' && c != '\r' && c != ESCAPE;
! 276: wclrtoeol(win), wrefresh(win))
! 277: {
! 278: if (c == -1)
! 279: continue;
! 280: else if (c == erasechar()) /* process erase character */
! 281: {
! 282: if (sp > buf)
! 283: {
! 284: sp--;
! 285: for (i = strlen(unctrl(*sp)); i; i--)
! 286: waddch(win, '\b');
! 287: }
! 288: continue;
! 289: }
! 290: else if (c == killchar()) /* process kill character */
! 291: {
! 292: sp = buf;
! 293: wmove(win, oy, ox);
! 294: continue;
! 295: }
! 296: else if (sp == buf)
! 297: {
! 298: if (c == '-' && win != stdscr)
! 299: break;
! 300: else if (c == '~')
! 301: {
! 302: strcpy(buf, home);
! 303: waddstr(win, home);
! 304: sp += strlen(home);
! 305: continue;
! 306: }
! 307: }
! 308: if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
! 309: putchar(CTRL('G'));
! 310: else
! 311: {
! 312: *sp++ = (char) c;
! 313: waddstr(win, unctrl(c));
! 314: }
! 315: }
! 316: *sp = '\0';
! 317: if (sp > buf) /* only change option if something has been typed */
! 318: strucpy(opt, buf, strlen(buf));
! 319: mvwprintw(win, oy, ox, "%s\n", opt);
! 320: wrefresh(win);
! 321: if (win == stdscr)
! 322: mpos += (int)(sp - buf);
! 323: if (c == '-')
! 324: return MINUS;
! 325: else if (c == ESCAPE)
! 326: return QUIT;
! 327: else
! 328: return NORM;
! 329: }
! 330:
! 331: /*
! 332: * get_inv_t
! 333: * Get an inventory type name
! 334: */
! 335: int
! 336: get_inv_t(void *vp, WINDOW *win)
! 337: {
! 338: int *ip = (int *) vp;
! 339: int oy, ox;
! 340: int op_bad;
! 341:
! 342: op_bad = TRUE;
! 343: getyx(win, oy, ox);
! 344: waddstr(win, inv_t_name[*ip]);
! 345: while (op_bad)
! 346: {
! 347: wmove(win, oy, ox);
! 348: wrefresh(win);
! 349: switch (wreadchar(win))
! 350: {
! 351: case 'o':
! 352: case 'O':
! 353: *ip = INV_OVER;
! 354: op_bad = FALSE;
! 355: break;
! 356: case 's':
! 357: case 'S':
! 358: *ip = INV_SLOW;
! 359: op_bad = FALSE;
! 360: break;
! 361: case 'c':
! 362: case 'C':
! 363: *ip = INV_CLEAR;
! 364: op_bad = FALSE;
! 365: break;
! 366: case '\n':
! 367: case '\r':
! 368: op_bad = FALSE;
! 369: break;
! 370: case ESCAPE:
! 371: return QUIT;
! 372: case '-':
! 373: return MINUS;
! 374: default:
! 375: wmove(win, oy, ox + 15);
! 376: waddstr(win, "(O, S, or C)");
! 377: }
! 378: }
! 379: mvwprintw(win, oy, ox, "%s\n", inv_t_name[*ip]);
! 380: return NORM;
! 381: }
! 382:
! 383:
! 384: #ifdef MASTER
! 385: /*
! 386: * get_num:
! 387: * Get a numeric option
! 388: */
! 389: int
! 390: get_num(void *vp, WINDOW *win)
! 391: {
! 392: int *opt = (int *) vp;
! 393: int i;
! 394: static char buf[MAXSTR];
! 395:
! 396: if ((i = get_str(buf, win)) == NORM)
! 397: *opt = atoi(buf);
! 398: return i;
! 399: }
! 400: #endif
! 401:
! 402: /*
! 403: * parse_opts:
! 404: * Parse options from string, usually taken from the environment.
! 405: * The string is a series of comma seperated values, with booleans
! 406: * being stated as "name" (true) or "noname" (false), and strings
! 407: * being "name=....", with the string being defined up to a comma
! 408: * or the end of the entire option string.
! 409: */
! 410:
! 411: void
! 412: parse_opts(char *str)
! 413: {
! 414: char *sp;
! 415: const OPTION *op;
! 416: int len;
! 417: const char **i;
! 418: char *start;
! 419:
! 420: while (*str)
! 421: {
! 422: /*
! 423: * Get option name
! 424: */
! 425: for (sp = str; isalpha((int)*sp); sp++)
! 426: continue;
! 427: len = (int)(sp - str);
! 428: /*
! 429: * Look it up and deal with it
! 430: */
! 431: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 432: {
! 433: if (!allowchange(op))
! 434: continue;
! 435: if (EQSTR(str, op->o_name, len))
! 436: {
! 437: if (op->o_putfunc == put_bool) /* if option is a boolean */
! 438: *(int *)op->o_opt = TRUE; /* NOSTRICT */
! 439: else /* string option */
! 440: {
! 441: /*
! 442: * Skip to start of string value
! 443: */
! 444: for (str = sp + 1; *str == '='; str++)
! 445: continue;
! 446: if (*str == '~')
! 447: {
! 448: strcpy((char *) op->o_opt, home); /* NOSTRICT */
! 449: start = (char *) op->o_opt + strlen(home);/* NOSTRICT */
! 450: while (*++str == '/')
! 451: continue;
! 452: }
! 453: else
! 454: start = (char *) op->o_opt; /* NOSTRICT */
! 455: /*
! 456: * Skip to end of string value
! 457: */
! 458: for (sp = str + 1; *sp && *sp != ','; sp++)
! 459: continue;
! 460: /*
! 461: * check for type of inventory
! 462: */
! 463: if (op->o_putfunc == put_inv_t)
! 464: {
! 465: if (islower((int)*str))
! 466: *str = (char) toupper(*str);
! 467: for (i = inv_t_name; i <= &inv_t_name[INV_CLEAR]; i++)
! 468: if (strncmp(str, *i, sp - str) == 0)
! 469: {
! 470: inv_type = (int)(i - inv_t_name);
! 471: break;
! 472: }
! 473: }
! 474: else
! 475: strucpy(start, str, (size_t)(sp - str));
! 476: }
! 477: break;
! 478: }
! 479: /*
! 480: * check for "noname" for booleans
! 481: */
! 482: else if (op->o_putfunc == put_bool
! 483: && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
! 484: {
! 485: *(int *)op->o_opt = FALSE; /* NOSTRICT */
! 486: break;
! 487: }
! 488: }
! 489:
! 490: /*
! 491: * skip to start of next option name
! 492: */
! 493: while (*sp && !isalpha((int)*sp))
! 494: sp++;
! 495: str = sp;
! 496: }
! 497: }
! 498:
! 499: /*
! 500: * strucpy:
! 501: * Copy string using unctrl for things
! 502: */
! 503:
! 504: void
! 505: strucpy(char *s1, const char *s2, size_t len)
! 506: {
! 507: if (len > MAXINP)
! 508: len = MAXINP;
! 509: while (len--)
! 510: {
! 511: if (isprint((int)*s2) || *s2 == ' ')
! 512: *s1++ = *s2;
! 513: s2++;
! 514: }
! 515: *s1 = '\0';
! 516: }
! 517:
! 518: /* Tells whether the user is allowed to change the option. */
! 519: int
! 520: allowchange(const OPTION *opt)
! 521: {
! 522: if (!use_savedir)
! 523: return TRUE;
! 524: if (!strcmp(opt->o_name, "name"))
! 525: return FALSE;
! 526: if (!strcmp(opt->o_name, "file"))
! 527: return FALSE;
! 528: return TRUE;
! 529: }
CVSweb