Annotation of early-roguelike/rogue3/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: * @(#)options.c 3.3 (Berkeley) 5/25/81
! 7: *
! 8: * 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: #include <stdlib.h>
! 16: #include "curses.h"
! 17: #include <ctype.h>
! 18: #include <string.h>
! 19: #include "machdep.h"
! 20: #include "rogue.h"
! 21:
! 22: #define NUM_OPTS (sizeof optlist / sizeof (OPTION))
! 23:
! 24: /*
! 25: * description of an option and what to do with it
! 26: */
! 27: struct optstruct {
! 28: char *o_name; /* option name */
! 29: char *o_prompt; /* prompt for interactive entry */
! 30: void *o_opt; /* pointer to thing to set */
! 31: void (*o_putfunc)(); /* function to print value */
! 32: int (*o_getfunc)(); /* function to get value interactively */
! 33: };
! 34:
! 35: typedef struct optstruct OPTION;
! 36:
! 37: int allowchange(OPTION *opt); /* doesn't need to be externally visible */
! 38:
! 39: OPTION optlist[] = {
! 40: {"terse", "Terse output: ",
! 41: (int *) &terse, put_bool, get_bool },
! 42: {"flush", "Flush typeahead during battle: ",
! 43: (int *) &fight_flush, put_bool, get_bool },
! 44: {"jump", "Show position only at end of run: ",
! 45: (int *) &jump, put_bool, get_bool },
! 46: {"step", "Do inventories one line at a time: ",
! 47: (int *) &slow_invent, put_bool, get_bool },
! 48: {"askme", "Ask me about unidentified things: ",
! 49: (int *) &askme, put_bool, get_bool },
! 50: {"name", "Name: ",
! 51: (int *) whoami, put_str, get_str },
! 52: {"fruit", "Fruit: ",
! 53: (int *) fruit, put_str, get_str },
! 54: {"file", "Save file: ",
! 55: (int *) file_name, put_str, get_str }
! 56: };
! 57:
! 58: /*
! 59: * print and then set options from the terminal
! 60: */
! 61: void
! 62: option()
! 63: {
! 64: OPTION *op;
! 65: int retval;
! 66:
! 67: wclear(hw);
! 68: touchwin(hw);
! 69: /*
! 70: * Display current values of options
! 71: */
! 72: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 73: {
! 74: if (allowchange(op))
! 75: {
! 76: waddstr(hw, op->o_prompt);
! 77: (*op->o_putfunc)(op->o_opt);
! 78: waddch(hw, '\n');
! 79: }
! 80: }
! 81: /*
! 82: * Set values
! 83: */
! 84: wmove(hw, 0, 0);
! 85: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 86: {
! 87: if (!allowchange(op))
! 88: continue;
! 89: waddstr(hw, op->o_prompt);
! 90: if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
! 91: {
! 92: if (retval == QUIT)
! 93: break;
! 94: #if 0
! 95: /* Support for MINUS has been removed because making it work with
! 96: * hidden unchangable options without underflowing optlist will
! 97: * require a complete rewrite. And it should also be rewritten
! 98: * so option() doesn't count on get_str() to put the cursor in the
! 99: * right place, because that makes it a pain to understand.
! 100: */
! 101: else if (op > optlist) { /* retval == MINUS */
! 102: wmove(hw, (int)(op - optlist) - 1, 0);
! 103: op -= 2;
! 104: }
! 105: else /* trying to back up beyond the top */
! 106: {
! 107: beep();
! 108: wmove(hw, 0, 0);
! 109: op--;
! 110: }
! 111: #else
! 112: break;
! 113: #endif
! 114: }
! 115: }
! 116: /*
! 117: * Switch back to original screen
! 118: */
! 119: mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
! 120: draw(hw);
! 121: wait_for(hw,' ');
! 122: clearok(cw, TRUE);
! 123: touchwin(cw);
! 124: after = FALSE;
! 125: }
! 126:
! 127: /*
! 128: * put out a boolean
! 129: */
! 130: void
! 131: put_bool(void *b)
! 132: {
! 133: waddstr(hw, *(int *)b ? "True" : "False");
! 134: }
! 135:
! 136: /*
! 137: * put out a string
! 138: */
! 139: void
! 140: put_str(void *str)
! 141: {
! 142: waddstr(hw, (char *) str);
! 143: }
! 144:
! 145: /*
! 146: * allow changing a boolean option and print it out
! 147: */
! 148:
! 149: int
! 150: get_bool(void *vp, WINDOW *win)
! 151: {
! 152: int *bp = (int *) vp;
! 153: int oy, ox;
! 154: int op_bad;
! 155:
! 156: op_bad = TRUE;
! 157: getyx(win, oy, ox);
! 158: waddstr(win, *bp ? "True" : "False");
! 159: while(op_bad)
! 160: {
! 161: wmove(win, oy, ox);
! 162: draw(win);
! 163: switch (readchar(win))
! 164: {
! 165: case 't':
! 166: case 'T':
! 167: *bp = TRUE;
! 168: op_bad = FALSE;
! 169: break;
! 170: case 'f':
! 171: case 'F':
! 172: *bp = FALSE;
! 173: op_bad = FALSE;
! 174: break;
! 175: case '\n':
! 176: case '\r':
! 177: op_bad = FALSE;
! 178: break;
! 179: case '\033':
! 180: case '\007':
! 181: return QUIT;
! 182: case '-':
! 183: return MINUS;
! 184: default:
! 185: mvwaddstr(win, oy, ox + 10, "(T or F)");
! 186: }
! 187: }
! 188: wmove(win, oy, ox);
! 189: waddstr(win, *bp ? "True" : "False");
! 190: waddch(win, '\n');
! 191: return NORM;
! 192: }
! 193:
! 194: /*
! 195: * set a string option
! 196: */
! 197: int
! 198: get_str(void *vopt, WINDOW *win)
! 199: {
! 200: char *opt = (char *) vopt;
! 201: char *sp;
! 202: int c, oy, ox;
! 203: char buf[80];
! 204:
! 205: draw(win);
! 206: getyx(win, oy, ox);
! 207: /*
! 208: * loop reading in the string, and put it in a temporary buffer
! 209: */
! 210: for (sp = buf;
! 211: (c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007';
! 212: wclrtoeol(win), draw(win))
! 213: {
! 214: if (c == -1)
! 215: continue;
! 216: else if (c == md_erasechar()) /* process erase character */
! 217: {
! 218: if (sp > buf)
! 219: {
! 220: int i;
! 221: int myx, myy;
! 222:
! 223: sp--;
! 224:
! 225: for (i = (int) strlen(unctrl(*sp)); i; i--)
! 226: {
! 227: getyx(win,myy,myx);
! 228: if ((myx == 0)&& (myy > 0))
! 229: {
! 230: wmove(win,myy-1,getmaxx(win)-1);
! 231: waddch(win,' ');
! 232: wmove(win,myy-1,getmaxx(win)-1);
! 233: }
! 234: else
! 235: waddch(win, '\b');
! 236: }
! 237: }
! 238: continue;
! 239: }
! 240: else if (c == md_killchar()) /* process kill character */
! 241: {
! 242: sp = buf;
! 243: wmove(win, oy, ox);
! 244: continue;
! 245: }
! 246: else if (sp == buf)
! 247: if (c == '-')
! 248: break;
! 249: else if (c == '~')
! 250: {
! 251: strcpy(buf, home);
! 252: waddstr(win, home);
! 253: sp += strlen(home);
! 254: continue;
! 255: }
! 256:
! 257: if ((sp - buf) < 78) /* Avoid overflow */
! 258: {
! 259: *sp++ = c;
! 260: waddstr(win, unctrl(c));
! 261: }
! 262: }
! 263: *sp = '\0';
! 264: if (sp > buf) /* only change option if something has been typed */
! 265: strucpy(opt, buf, strlen(buf));
! 266: wmove(win, oy, ox);
! 267: waddstr(win, opt);
! 268: waddch(win, '\n');
! 269: draw(win);
! 270: if (win == cw)
! 271: mpos += (int)(sp - buf);
! 272: if (c == '-')
! 273: return MINUS;
! 274: else if (c == '\033' || c == '\007')
! 275: return QUIT;
! 276: else
! 277: return NORM;
! 278: }
! 279:
! 280: /*
! 281: * parse options from string, usually taken from the environment.
! 282: * the string is a series of comma seperated values, with booleans
! 283: * being stated as "name" (true) or "noname" (false), and strings
! 284: * being "name=....", with the string being defined up to a comma
! 285: * or the end of the entire option string.
! 286: */
! 287:
! 288: void
! 289: parse_opts(char *str)
! 290: {
! 291: char *sp;
! 292: OPTION *op;
! 293: int len;
! 294:
! 295: while (*str)
! 296: {
! 297: /*
! 298: * Get option name
! 299: */
! 300: for (sp = str; isalpha(*sp); sp++)
! 301: continue;
! 302: len = (int)(sp - str);
! 303: /*
! 304: * Look it up and deal with it
! 305: */
! 306: for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
! 307: {
! 308: /* If using system savefiles, changing your name or the
! 309: save file is not allowed. */
! 310: if (!allowchange(op))
! 311: continue;
! 312: if (EQSTR(str, op->o_name, len))
! 313: {
! 314: if (op->o_putfunc == put_bool) /* if option is a boolean */
! 315: *(int *)op->o_opt = TRUE;
! 316: else /* string option */
! 317: {
! 318: char *start;
! 319: /*
! 320: * Skip to start of string value
! 321: */
! 322: for (str = sp + 1; *str == '='; str++)
! 323: continue;
! 324: if (*str == '~')
! 325: {
! 326: strcpy((char *) op->o_opt, home);
! 327: start = (char *) op->o_opt + strlen(home);
! 328: while (*++str == '/')
! 329: continue;
! 330: }
! 331: else
! 332: start = (char *) op->o_opt;
! 333: /*
! 334: * Skip to end of string value
! 335: */
! 336: for (sp = str + 1; *sp && *sp != ','; sp++)
! 337: continue;
! 338: strucpy(start, str, sp - str);
! 339: }
! 340: break;
! 341: }
! 342: /*
! 343: * check for "noname" for booleans
! 344: */
! 345: else if (op->o_putfunc == put_bool
! 346: && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
! 347: {
! 348: *(int *)op->o_opt = FALSE;
! 349: break;
! 350: }
! 351: }
! 352:
! 353: /*
! 354: * skip to start of next option name
! 355: */
! 356: while (*sp && !isalpha(*sp))
! 357: sp++;
! 358: str = sp;
! 359: }
! 360: }
! 361:
! 362: /*
! 363: * copy string using unctrl for things
! 364: */
! 365: void
! 366: strucpy(char *s1, char *s2, size_t len)
! 367: {
! 368: const char *sp;
! 369:
! 370: while (len--)
! 371: {
! 372: sp = unctrl(*s2);
! 373: strcpy(s1, sp);
! 374: s1 += strlen(sp);
! 375: s2++;
! 376: }
! 377: *s1 = '\0';
! 378: }
! 379:
! 380: /* Tells whether the user is allowed to change the option. */
! 381: int allowchange(OPTION *opt)
! 382: {
! 383: if (!use_savedir)
! 384: return 1;
! 385: if (!strcmp(opt->o_name, "name"))
! 386: return 0;
! 387: if (!strcmp(opt->o_name, "file"))
! 388: return 0;
! 389: return 1;
! 390: }
CVSweb