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