Annotation of early-roguelike/rogue3/options.c, Revision 1.1.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