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