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