Mercurial > hg > early-roguelike
diff rogue3/options.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | e676d52b5d09 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/options.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,353 @@ +/* + * This file has all the code for the option command. + * I would rather this command were not necessary, but + * it is the only way to keep the wolves off of my back. + * + * @(#)options.c 3.3 (Berkeley) 5/25/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <stdlib.h> +#include "curses.h" +#include <ctype.h> +#include <string.h> +#include "machdep.h" +#include "rogue.h" + +#define NUM_OPTS (sizeof optlist / sizeof (OPTION)) + +/* + * description of an option and what to do with it + */ +struct optstruct { + char *o_name; /* option name */ + char *o_prompt; /* prompt for interactive entry */ + void *o_opt; /* pointer to thing to set */ + void (*o_putfunc)(); /* function to print value */ + int (*o_getfunc)(); /* function to get value interactively */ +}; + +typedef struct optstruct OPTION; + +OPTION optlist[] = { + {"terse", "Terse output: ", + (int *) &terse, put_bool, get_bool }, + {"flush", "Flush typeahead during battle: ", + (int *) &fight_flush, put_bool, get_bool }, + {"jump", "Show position only at end of run: ", + (int *) &jump, put_bool, get_bool }, + {"step", "Do inventories one line at a time: ", + (int *) &slow_invent, put_bool, get_bool }, + {"askme", "Ask me about unidentified things: ", + (int *) &askme, put_bool, get_bool }, + {"name", "Name: ", + (int *) whoami, put_str, get_str }, + {"fruit", "Fruit: ", + (int *) fruit, put_str, get_str }, + {"file", "Save file: ", + (int *) file_name, put_str, get_str } +}; + +/* + * print and then set options from the terminal + */ +void +option() +{ + OPTION *op; + int retval; + + wclear(hw); + touchwin(hw); + /* + * Display current values of options + */ + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + { + waddstr(hw, op->o_prompt); + (*op->o_putfunc)(op->o_opt); + waddch(hw, '\n'); + } + /* + * Set values + */ + wmove(hw, 0, 0); + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + { + waddstr(hw, op->o_prompt); + if ((retval = (*op->o_getfunc)(op->o_opt, hw))) + if (retval == QUIT) + break; + else if (op > optlist) { /* MINUS */ + wmove(hw, (int)(op - optlist) - 1, 0); + op -= 2; + } + else /* trying to back up beyond the top */ + { + beep(); + wmove(hw, 0, 0); + op--; + } + } + /* + * Switch back to original screen + */ + mvwaddstr(hw, LINES-1, 0, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + clearok(cw, TRUE); + touchwin(cw); + after = FALSE; +} + +/* + * put out a boolean + */ +void +put_bool(void *b) +{ + waddstr(hw, *(int *)b ? "True" : "False"); +} + +/* + * put out a string + */ +void +put_str(void *str) +{ + waddstr(hw, (char *) str); +} + +/* + * allow changing a boolean option and print it out + */ + +int +get_bool(void *vp, WINDOW *win) +{ + int *bp = (int *) vp; + int oy, ox; + int op_bad; + + op_bad = TRUE; + getyx(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + while(op_bad) + { + wmove(win, oy, ox); + draw(win); + switch (readchar(win)) + { + case 't': + case 'T': + *bp = TRUE; + op_bad = FALSE; + break; + case 'f': + case 'F': + *bp = FALSE; + op_bad = FALSE; + break; + case '\n': + case '\r': + op_bad = FALSE; + break; + case '\033': + case '\007': + return QUIT; + case '-': + return MINUS; + default: + mvwaddstr(win, oy, ox + 10, "(T or F)"); + } + } + wmove(win, oy, ox); + waddstr(win, *bp ? "True" : "False"); + waddch(win, '\n'); + return NORM; +} + +/* + * set a string option + */ +int +get_str(void *vopt, WINDOW *win) +{ + char *opt = (char *) vopt; + char *sp; + int c, oy, ox; + char buf[80]; + + draw(win); + getyx(win, oy, ox); + /* + * loop reading in the string, and put it in a temporary buffer + */ + for (sp = buf; + (c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007'; + wclrtoeol(win), draw(win)) + { + if (c == -1) + continue; + else if (c == md_erasechar()) /* process erase character */ + { + if (sp > buf) + { + int i; + int myx, myy; + + sp--; + + for (i = (int) strlen(unctrl(*sp)); i; i--) + { + getyx(win,myy,myx); + if ((myx == 0)&& (myy > 0)) + { + wmove(win,myy-1,getmaxx(win)-1); + waddch(win,' '); + wmove(win,myy-1,getmaxx(win)-1); + } + else + waddch(win, '\b'); + } + } + continue; + } + else if (c == md_killchar()) /* process kill character */ + { + sp = buf; + wmove(win, oy, ox); + continue; + } + else if (sp == buf) + if (c == '-') + break; + else if (c == '~') + { + strcpy(buf, home); + waddstr(win, home); + sp += strlen(home); + continue; + } + + if ((sp - buf) < 78) /* Avoid overflow */ + { + *sp++ = c; + waddstr(win, unctrl(c)); + } + } + *sp = '\0'; + if (sp > buf) /* only change option if something has been typed */ + strucpy(opt, buf, strlen(buf)); + wmove(win, oy, ox); + waddstr(win, opt); + waddch(win, '\n'); + draw(win); + if (win == cw) + mpos += (int)(sp - buf); + if (c == '-') + return MINUS; + else if (c == '\033' || c == '\007') + return QUIT; + else + return NORM; +} + +/* + * parse options from string, usually taken from the environment. + * the string is a series of comma seperated values, with booleans + * being stated as "name" (true) or "noname" (false), and strings + * being "name=....", with the string being defined up to a comma + * or the end of the entire option string. + */ + +void +parse_opts(char *str) +{ + char *sp; + OPTION *op; + int len; + + while (*str) + { + /* + * Get option name + */ + for (sp = str; isalpha(*sp); sp++) + continue; + len = (int)(sp - str); + /* + * Look it up and deal with it + */ + for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++) + if (EQSTR(str, op->o_name, len)) + { + if (op->o_putfunc == put_bool) /* if option is a boolean */ + *(int *)op->o_opt = TRUE; + else /* string option */ + { + char *start; + /* + * Skip to start of string value + */ + for (str = sp + 1; *str == '='; str++) + continue; + if (*str == '~') + { + strcpy((char *) op->o_opt, home); + start = (char *) op->o_opt + strlen(home); + while (*++str == '/') + continue; + } + else + start = (char *) op->o_opt; + /* + * Skip to end of string value + */ + for (sp = str + 1; *sp && *sp != ','; sp++) + continue; + strucpy(start, str, sp - str); + } + break; + } + /* + * check for "noname" for booleans + */ + else if (op->o_putfunc == put_bool + && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2)) + { + *(int *)op->o_opt = FALSE; + break; + } + + /* + * skip to start of next option name + */ + while (*sp && !isalpha(*sp)) + sp++; + str = sp; + } +} + +/* + * copy string using unctrl for things + */ +void +strucpy(char *s1, char *s2, size_t len) +{ + const char *sp; + + while (len--) + { + sp = unctrl(*s2); + strcpy(s1, sp); + s1 += strlen(sp); + s2++; + } + *s1 = '\0'; +}