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