Annotation of early-roguelike/xrogue/options.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: options.c - This file has all the code for the option command
! 3:
! 4: XRogue: Expeditions into the Dungeons of Doom
! 5: Copyright (C) 1991 Robert Pietkivitch
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: /*
! 20: * I would rather this command were not necessary, but
! 21: * it is the only way to keep the wolves off of my back.
! 22: */
! 23:
! 24: #include <curses.h>
! 25: #include <ctype.h>
! 26: #include <string.h>
! 27: #include "rogue.h"
! 28:
! 29: #define NUM_OPTS (sizeof optlist / sizeof (OPTION))
! 30:
! 31: /*
! 32: * description of an option and what to do with it
! 33: */
! 34: struct optstruct {
! 35: char *o_name; /* option name */
! 36: char *o_prompt; /* prompt for interactive entry */
! 37: void *o_opt; /* pointer to thing to set */
! 38: void (*o_putfunc)(); /* function to print value */
! 39: int (*o_getfunc)(); /* function to get value interactively */
! 40: };
! 41:
! 42: typedef struct optstruct OPTION;
! 43:
! 44: int get_ro(WINDOW *win, int oy, int ox);
! 45: void put_bool(bool *b, WINDOW *win);
! 46: int get_bool(bool *bp, WINDOW *win);
! 47: void put_str(char *str, WINDOW *win);
! 48: int get_str(char *opt, WINDOW *win);
! 49: void put_abil(int *ability, WINDOW *win);
! 50: int get_abil(int *abil, WINDOW *win);
! 51: void put_quest(int *quest, WINDOW *win);
! 52: int get_quest(int *quest, WINDOW *win);
! 53: int get_default(bool *bp, WINDOW *win);
! 54: int get_str_prot(char *opt, WINDOW *win);
! 55: int get_score(char *opt, WINDOW *win);
! 56: bool allowchange(OPTION *op);
! 57:
! 58: OPTION optlist[] = {
! 59: {"terse", "Terse output: ",
! 60: (void *) &terse, put_bool, get_bool },
! 61: {"flush", "Flush typeahead during battle: ",
! 62: (void *) &fight_flush, put_bool, get_bool },
! 63: {"jump", "Show position only at end of run: ",
! 64: (void *) &jump, put_bool, get_bool },
! 65: {"step", "Do inventories one line at a time: ",
! 66: (void *) &slow_invent, put_bool, get_bool },
! 67: {"askme", "Ask me about unidentified things: ",
! 68: (void *) &askme, put_bool, get_bool },
! 69: {"pickup", "Pick things up automatically: ",
! 70: (void *) &auto_pickup, put_bool, get_bool },
! 71: {"overlay", "Overlay menu: ",
! 72: (void *) &menu_overlay, put_bool, get_bool },
! 73: {"name", "Name: ",
! 74: (void *) whoami, put_str, get_str_prot },
! 75: {"file", "Save file: ",
! 76: (void *) file_name, put_str, get_str_prot },
! 77: {"score", "Score file: ",
! 78: (void *) score_file, put_str, get_score },
! 79: {"class", "Character type: ",
! 80: (void *) &char_type, put_abil, get_abil },
! 81: {"quest", "Quest item: ",
! 82: (void *) &quest_item, put_quest, get_quest },
! 83: {"default", "Default Attributes: ",
! 84: (void *) &def_attr, put_bool, get_default }
! 85: };
! 86:
! 87: /*
! 88: * The default attribute field is read-only
! 89: */
! 90:
! 91: int
! 92: get_default(bool *bp, WINDOW *win)
! 93: {
! 94: register int oy, ox;
! 95:
! 96: getyx(win, oy, ox);
! 97: put_bool(bp, win);
! 98: return get_ro(win, oy, ox);
! 99: }
! 100:
! 101: /*
! 102: * The ability (class) field is read-only
! 103: */
! 104:
! 105: int
! 106: get_abil(int *abil, WINDOW *win)
! 107: {
! 108: register int oy, ox;
! 109:
! 110: getyx(win, oy, ox);
! 111: put_abil(abil, win);
! 112: return get_ro(win, oy, ox);
! 113: }
! 114:
! 115: /*
! 116: * The quest field is read-only
! 117: */
! 118:
! 119: int
! 120: get_quest(int *quest, WINDOW *win)
! 121: {
! 122: register int oy, ox;
! 123:
! 124: getyx(win, oy, ox);
! 125: waddstr(win, rel_magic[*quest].mi_name);
! 126: return get_ro(win, oy, ox);
! 127: }
! 128:
! 129: /*
! 130: * get_ro:
! 131: * "Get" a read-only value.
! 132: */
! 133:
! 134: int
! 135: get_ro(WINDOW *win, int oy, int ox)
! 136: {
! 137: register int ny, nx;
! 138: register bool op_bad;
! 139:
! 140: op_bad = TRUE;
! 141: getyx(win, ny, nx);
! 142: while(op_bad)
! 143: {
! 144: wmove(win, oy, ox);
! 145: draw(win);
! 146: switch (wgetch(win))
! 147: {
! 148: case '\n':
! 149: case '\r':
! 150: op_bad = FALSE;
! 151: break;
! 152: case '\033':
! 153: case '\007':
! 154: return QUIT;
! 155: case '-':
! 156: return MINUS;
! 157: default:
! 158: mvwaddstr(win, ny, nx + 5, "(no change allowed)");
! 159: }
! 160: }
! 161: wmove(win, ny, nx + 5);
! 162: wclrtoeol(win);
! 163: wmove(win, ny, nx);
! 164: waddch(win, '\n');
! 165: return NORM;
! 166: }
! 167:
! 168: /*
! 169: * allow changing a boolean option and print it out
! 170: */
! 171:
! 172: int
! 173: get_bool(bool *bp, WINDOW *win)
! 174: {
! 175: register int oy, ox;
! 176: register bool op_bad;
! 177:
! 178: op_bad = TRUE;
! 179: getyx(win, oy, ox);
! 180: waddstr(win, *bp ? "True" : "False");
! 181: while(op_bad)
! 182: {
! 183: wmove(win, oy, ox);
! 184: draw(win);
! 185: switch (wgetch(win))
! 186: {
! 187: case 't':
! 188: case 'T':
! 189: *bp = TRUE;
! 190: op_bad = FALSE;
! 191: break;
! 192: case 'f':
! 193: case 'F':
! 194: *bp = FALSE;
! 195: op_bad = FALSE;
! 196: break;
! 197: case '\n':
! 198: case '\r':
! 199: op_bad = FALSE;
! 200: break;
! 201: case '\033':
! 202: case '\007':
! 203: return QUIT;
! 204: case '-':
! 205: return MINUS;
! 206: default:
! 207: mvwaddstr(win, oy, ox + 10, "(T or F)");
! 208: }
! 209: }
! 210: wmove(win, oy, ox);
! 211: wclrtoeol(win);
! 212: waddstr(win, *bp ? "True" : "False");
! 213: waddch(win, '\n');
! 214: return NORM;
! 215: }
! 216:
! 217: /*
! 218: * set a string option
! 219: */
! 220:
! 221: int
! 222: get_str(char *opt, WINDOW *win)
! 223: {
! 224: register char *sp;
! 225: register int c, oy, ox;
! 226: char buf[LINELEN];
! 227:
! 228: draw(win);
! 229: getyx(win, oy, ox);
! 230: /*
! 231: * loop reading in the string, and put it in a temporary buffer
! 232: */
! 233: for (sp = buf;
! 234: (c = wgetch(win)) != '\n' &&
! 235: c != '\r' &&
! 236: c != '\033' &&
! 237: c != '\007' &&
! 238: sp < &buf[LINELEN-1];
! 239: wclrtoeol(win), draw(win))
! 240: {
! 241: if (c == -1)
! 242: continue;
! 243: else if (c == erasechar()) /* process erase character */
! 244: {
! 245: if (sp > buf)
! 246: {
! 247: register int i;
! 248:
! 249: sp--;
! 250: for (i = strlen(unctrl(*sp)); i; i--)
! 251: waddch(win, '\b');
! 252: }
! 253: continue;
! 254: }
! 255: else if (c == killchar()) /* process kill character */
! 256: {
! 257: sp = buf;
! 258: wmove(win, oy, ox);
! 259: continue;
! 260: }
! 261: else if (sp == buf)
! 262: if (c == '-' && win == hw) /* To move back a line in hw */
! 263: break;
! 264: else if (c == '~')
! 265: {
! 266: strcpy(buf, home);
! 267: waddstr(win, home);
! 268: sp += strlen(home);
! 269: continue;
! 270: }
! 271: *sp++ = c;
! 272: waddstr(win, unctrl(c));
! 273: }
! 274: *sp = '\0';
! 275: if (sp > buf) /* only change option if something has been typed */
! 276: strucpy(opt, buf, strlen(buf));
! 277: wmove(win, oy, ox);
! 278: waddstr(win, opt);
! 279: waddch(win, '\n');
! 280: draw(win);
! 281: if (win == msgw)
! 282: mpos += sp - buf;
! 283: if (c == '-')
! 284: return MINUS;
! 285: else if (c == '\033' || c == '\007')
! 286: return QUIT;
! 287: else
! 288: return NORM;
! 289: }
! 290:
! 291: /*
! 292: * print and then set options from the terminal
! 293: */
! 294:
! 295: void
! 296: option(void)
! 297: {
! 298: register OPTION *op;
! 299: register int retval;
! 300:
! 301: wclear(hw);
! 302: touchwin(hw);
! 303: /*
! 304: * Display current values of options
! 305: */
! 306: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
! 307: {
! 308: waddstr(hw, op->o_prompt);
! 309: (*op->o_putfunc)(op->o_opt, hw);
! 310: waddch(hw, '\n');
! 311: }
! 312: /*
! 313: * Set values
! 314: */
! 315: wmove(hw, 0, 0);
! 316: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
! 317: {
! 318: waddstr(hw, op->o_prompt);
! 319:
! 320: retval = (*op->o_getfunc)(op->o_opt, hw);
! 321:
! 322: if (retval)
! 323: if (retval == QUIT)
! 324: break;
! 325: else if (op > optlist) { /* MINUS */
! 326: wmove(hw, (op - optlist) - 1, 0);
! 327: op -= 2;
! 328: }
! 329: else /* trying to back up beyond the top */
! 330: {
! 331: putchar('\007');
! 332: wmove(hw, 0, 0);
! 333: op--;
! 334: }
! 335: }
! 336: /*
! 337: * Switch back to original screen
! 338: */
! 339: mvwaddstr(hw, lines-1, 0, spacemsg);
! 340: draw(hw);
! 341: wait_for(' ');
! 342: restscr(cw);
! 343: after = FALSE;
! 344: }
! 345:
! 346: /*
! 347: * parse options from string, usually taken from the environment.
! 348: * the string is a series of comma seperated values, with booleans
! 349: * being stated as "name" (true) or "noname" (false), and strings
! 350: * being "name=....", with the string being defined up to a comma
! 351: * or the end of the entire option string.
! 352: */
! 353:
! 354: void
! 355: parse_opts(char *str)
! 356: {
! 357: register char *sp;
! 358: register OPTION *op;
! 359: register int len;
! 360:
! 361: if (*str == '\"')
! 362: str++;
! 363:
! 364: while (*str)
! 365: {
! 366: /*
! 367: * Get option name
! 368: */
! 369:
! 370: for (sp = str; isalpha(*sp); sp++)
! 371: continue;
! 372: len = (char *)sp - str;
! 373: /*
! 374: * Look it up and deal with it
! 375: */
! 376: for (op = optlist; op < &optlist[NUM_OPTS]; op++)
! 377: {
! 378: if (EQSTR(str, op->o_name, len))
! 379: {
! 380: if (op->o_putfunc == put_bool) /* if option is a boolean */
! 381: *(bool *)op->o_opt = TRUE;
! 382: else /* string option */
! 383: {
! 384: register char *start;
! 385: char value[LINELEN];
! 386:
! 387: /*
! 388: * Skip to start of string value
! 389: */
! 390: for (str = sp + 1; *str == '=' || *str == ':'; str++)
! 391: continue;
! 392:
! 393: if (*str == '~')
! 394: {
! 395: strcpy((char *) value, home);
! 396: start = (char *) value + strlen(home);
! 397: while (*++str == '/')
! 398: continue;
! 399: }
! 400: else
! 401: start = (char *) value;
! 402: /*
! 403: * Skip to end of string value
! 404: */
! 405: for (sp = str + 1; *sp && *sp != ',' && *sp != '\"'; sp++)
! 406: continue;
! 407: strucpy(start, str, (char *) sp - str);
! 408:
! 409: /* Put the value into the option field */
! 410: if (op->o_putfunc != put_abil) {
! 411: if (allowchange(op))
! 412: strcpy((char *)op->o_opt, value);
! 413: }
! 414:
! 415: else if (*(int *)op->o_opt == -1) {
! 416: /* Only init ability once */
! 417: register int len = strlen(value);
! 418: register int i;
! 419:
! 420: for (i=0; i<NUM_CHARTYPES-1; i++) {
! 421: if (EQSTR(value, char_class[i].name, len)) {
! 422: *(int *)op->o_opt = i;
! 423: break;
! 424: }
! 425: }
! 426: }
! 427: }
! 428: break;
! 429: }
! 430: /*
! 431: * check for "noname" for booleans
! 432: */
! 433: else if (op->o_putfunc == put_bool
! 434: && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
! 435: {
! 436: *(bool *)op->o_opt = FALSE;
! 437: break;
! 438: }
! 439: }
! 440:
! 441: /*
! 442: * skip to start of next option name
! 443: */
! 444: while (*sp && !isalpha(*sp))
! 445: sp++;
! 446: str = sp;
! 447: }
! 448: }
! 449:
! 450:
! 451: /*
! 452: * print the default attributes
! 453: */
! 454:
! 455: /* put_default(b, win)
! 456: * bool *b;
! 457: * WINDOW *win;
! 458: * {
! 459: * waddstr(win, *b ? "True" : "False");
! 460: * }
! 461: */
! 462:
! 463: /*
! 464: * print the character type
! 465: */
! 466:
! 467: void
! 468: put_abil(int *ability, WINDOW *win)
! 469: {
! 470: waddstr(win, char_class[*ability].name);
! 471: }
! 472:
! 473: /*
! 474: * print out the quest
! 475: */
! 476:
! 477: void
! 478: put_quest(int *quest, WINDOW *win)
! 479: {
! 480: waddstr(win, rel_magic[*quest].mi_name);
! 481: }
! 482:
! 483: /*
! 484: * put out a boolean
! 485: */
! 486:
! 487: void
! 488: put_bool(bool *b, WINDOW *win)
! 489: {
! 490: waddstr(win, *b ? "True" : "False");
! 491: }
! 492:
! 493: /*
! 494: * put out a string
! 495: */
! 496:
! 497: void
! 498: put_str(char *str, WINDOW *win)
! 499: {
! 500: waddstr(win, str);
! 501: }
! 502:
! 503: /* Like get_str, but disallows changes when use_savedir is set. */
! 504: int
! 505: get_str_prot(char *opt, WINDOW *win)
! 506: {
! 507: int oy, ox;
! 508:
! 509: if (use_savedir) {
! 510: getyx(win, oy, ox);
! 511: waddstr(win, opt);
! 512: return get_ro(win, oy, ox);
! 513: }
! 514: else {
! 515: return get_str(opt, win);
! 516: }
! 517: }
! 518:
! 519: /* When getting the scorefile, the new file must be opened. */
! 520: int
! 521: get_score(char *optstr, WINDOW *win)
! 522: {
! 523: char old_score_file[LINELEN];
! 524: int status;
! 525:
! 526: if (use_savedir)
! 527: return get_str_prot(optstr, win);
! 528:
! 529: strcpy(old_score_file, optstr);
! 530: status = get_str(optstr, win);
! 531: if (status == NORM && strcmp(old_score_file, optstr))
! 532: {
! 533: if (scorefi != NULL)
! 534: fclose(scorefi);
! 535: scorefi = fopen(score_file, "rb+");
! 536: if (scorefi == NULL)
! 537: scorefi = fopen(score_file, "wb+");
! 538: }
! 539: return status;
! 540: }
! 541:
! 542: bool
! 543: allowchange(OPTION *op)
! 544: {
! 545: if (!use_savedir)
! 546: return TRUE;
! 547: if (!strcmp(op->o_name, "name"))
! 548: return FALSE;
! 549: if (!strcmp(op->o_name, "file"))
! 550: return FALSE;
! 551: if (!strcmp(op->o_name, "score"))
! 552: return FALSE;
! 553: return TRUE;
! 554: }
CVSweb