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