Neale Pickett
·
2011-10-13
pipes.c
1/*
2 * This file has all the code for the option command. I would rather
3 * this command were not necessary, but it is the only way to keep the
4 * wolves off of my back.
5 *
6 * @(#)pipes.c 4.24 (Berkeley) 05/10/83
7 */
8
9#include <curses.h>
10#include <ctype.h>
11#include "netprot.h"
12
13#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
14
15#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
16
17#ifndef attron
18# define erasechar() _tty.sg_erase
19# define killchar() _tty.sg_kill
20#endif
21
22/*
23 * description of an option and what to do with it
24 */
25struct optstruct {
26 char *o_name; /* option name */
27 char *o_prompt; /* prompt for interactive entry */
28 void *o_opt; /* pointer to thing to set */
29 /* function to print value */
30 void (*o_putfunc)(void *opt);
31 /* function to get value interactively */
32 int (*o_getfunc)(void *opt, WINDOW *win);
33};
34
35typedef struct optstruct OPTION;
36
37void pr_optname(OPTION *op);
38
39OPTION 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 {"seefloor", "Show the lamp-illuminated floor",
47 (int *) &See_floor, put_bool, get_sf },
48 {"passgo", "Follow turnings in passageways",
49 (int *) &Passgo, put_bool, get_bool },
50 {"tombstone", "Print out tombstone when killed",
51 (int *) &Tombstone, put_bool, get_bool },
52 {"inven", "Inventory style",
53 (int *) &Inv_type, put_inv_t, get_inv_t },
54 {"name", "Name",
55 (int *) Whoami, put_str, get_str },
56 {"fruit", "Fruit",
57 (int *) Fruit, put_str, get_str },
58 {"file", "Save file",
59 (int *) File_name, put_str, get_str }
60};
61
62/*
63 * option:
64 * Print and then set options from the terminal
65 */
66void
67option(void)
68{
69 OPTION *op;
70 int retval;
71
72 wclear(Hw);
73 /*
74 * Display current values of options
75 */
76 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
77 {
78 pr_optname(op);
79 (*op->o_putfunc)(op->o_opt);
80 waddch(Hw, '\n');
81 }
82 /*
83 * Set values
84 */
85 wmove(Hw, 0, 0);
86 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
87 {
88 pr_optname(op);
89 if ((retval = (*op->o_getfunc)(op->o_opt, Hw)))
90 if (retval == QUIT)
91 break;
92 else if (op > optlist) { /* MINUS */
93 wmove(Hw, (op - optlist) - 1, 0);
94 op -= 2;
95 }
96 else /* trying to back up beyond the top */
97 {
98 putchar('\007');
99 wmove(Hw, 0, 0);
100 op--;
101 }
102 }
103 /*
104 * Switch back to original screen
105 */
106 wmove(Hw, LINES - 1, 0);
107 waddstr(Hw, "--Press space to continue--");
108 wrefresh(Hw);
109 wait_for(' ');
110 clearok(curscr, TRUE);
111#ifdef attron
112 touchwin(stdscr);
113#endif
114 After = FALSE;
115}
116
117/*
118 * pr_optname:
119 * Print out the option name prompt
120 */
121void
122pr_optname(OPTION *op)
123{
124 wprintw(Hw, "%s (\"%s\"): ", op->o_prompt, op->o_name);
125}
126
127/*
128 * put_bool
129 * Put out a boolean
130 */
131void
132put_bool(void *b)
133{
134 waddstr(Hw, *(bool *) b ? "True" : "False");
135}
136
137/*
138 * put_str:
139 * Put out a string
140 */
141void
142put_str(void *str)
143{
144 waddstr(Hw, (char *) str);
145}
146
147/*
148 * put_inv_t:
149 * Put out an inventory type
150 */
151void
152put_inv_t(void *ip)
153{
154 waddstr(Hw, Inv_t_name[*(int *) ip]);
155}
156
157/*
158 * get_bool:
159 * Allow changing a boolean option and print it out
160 */
161int
162get_bool(void *vp, WINDOW *win)
163{
164 bool *bp = (bool *) vp;
165 int oy, ox;
166 bool op_bad;
167
168 op_bad = TRUE;
169 getyx(win, oy, ox);
170 waddstr(win, *bp ? "True" : "False");
171 while (op_bad)
172 {
173 wmove(win, oy, ox);
174 wrefresh(win);
175 switch (readchar())
176 {
177 case 't':
178 case 'T':
179 *bp = TRUE;
180 op_bad = FALSE;
181 break;
182 case 'f':
183 case 'F':
184 *bp = FALSE;
185 op_bad = FALSE;
186 break;
187 case '\n':
188 case '\r':
189 op_bad = FALSE;
190 break;
191 case ESCAPE:
192 return QUIT;
193 case '-':
194 return MINUS;
195 default:
196 wmove(win, oy, ox + 10);
197 waddstr(win, "(T or F)");
198 }
199 }
200 wmove(win, oy, ox);
201 waddstr(win, *bp ? "True" : "False");
202 waddch(win, '\n');
203 return NORM;
204}
205
206/*
207 * get_sf:
208 * Change value and handle transition problems from See_floor to
209 * !See_floor.
210 */
211int
212get_sf(void *vp, WINDOW *win)
213{
214 bool *bp = (bool *) vp;
215 bool was_sf;
216 int retval;
217
218 was_sf = See_floor;
219 retval = get_bool(bp, win);
220 if (retval == QUIT) return(QUIT);
221 if (was_sf != See_floor)
222 {
223 if (!See_floor) {
224 See_floor = TRUE;
225 erase_lamp(&Hero, Proom);
226 See_floor = FALSE;
227 }
228 else
229 look(FALSE);
230 }
231 return(NORM);
232}
233
234/*
235 * get_str:
236 * Set a string option
237 */
238#define MAXINP 50 /* max string to read from terminal or environment */
239
240int
241get_str(void *vopt, WINDOW *win)
242{
243 char *opt = (char *) vopt;
244 char *sp;
245 int c, oy, ox;
246 int i;
247 static char buf[MAXSTR];
248
249 getyx(win, oy, ox);
250 wrefresh(win);
251 /*
252 * loop reading in the string, and put it in a temporary buffer
253 */
254 for (sp = buf; (c = readchar()) != '\n' && c != '\r' && c != ESCAPE;
255 wclrtoeol(win), wrefresh(win))
256 {
257 if (c == -1)
258 continue;
259 else if (c == erasechar()) /* process erase character */
260 {
261 if (sp > buf)
262 {
263 sp--;
264 for (i = strlen(unctrl(*sp)); i; i--)
265 waddch(win, '\b');
266 }
267 continue;
268 }
269 else if (c == killchar()) /* process kill character */
270 {
271 sp = buf;
272 wmove(win, oy, ox);
273 continue;
274 }
275 else if (sp == buf)
276 {
277 if (c == '-' && win != stdscr)
278 break;
279 else if (c == '~')
280 {
281 strcpy(buf, Home);
282 waddstr(win, Home);
283 sp += strlen(Home);
284 continue;
285 }
286 }
287 if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
288 putchar(CTRL('G'));
289 else
290 {
291 *sp++ = c;
292 waddstr(win, unctrl(c));
293 }
294 }
295 *sp = '\0';
296 if (sp > buf) /* only change option if something has been typed */
297 strucpy(opt, buf, strlen(buf));
298 mvwprintw(win, oy, ox, "%s\n", opt);
299 wrefresh(win);
300 if (win == stdscr)
301 Mpos += sp - buf;
302 if (c == '-')
303 return MINUS;
304 else if (c == ESCAPE)
305 return QUIT;
306 else
307 return NORM;
308}
309
310/*
311 * get_inv_t
312 * Get an inventory type name
313 */
314int
315get_inv_t(void *vp, WINDOW *win)
316{
317 int *ip = (int *) vp;
318 int oy, ox;
319 bool op_bad;
320
321 op_bad = TRUE;
322 getyx(win, oy, ox);
323 waddstr(win, Inv_t_name[*ip]);
324 while (op_bad)
325 {
326 wmove(win, oy, ox);
327 wrefresh(win);
328 switch (readchar())
329 {
330 case 'o':
331 case 'O':
332 *ip = INV_OVER;
333 op_bad = FALSE;
334 break;
335 case 's':
336 case 'S':
337 *ip = INV_SLOW;
338 op_bad = FALSE;
339 break;
340 case 'c':
341 case 'C':
342 *ip = INV_CLEAR;
343 op_bad = FALSE;
344 break;
345 case '\n':
346 case '\r':
347 op_bad = FALSE;
348 break;
349 case ESCAPE:
350 return QUIT;
351 case '-':
352 return MINUS;
353 default:
354 wmove(win, oy, ox + 15);
355 waddstr(win, "(O, S, or C)");
356 }
357 }
358 mvwprintw(win, oy, ox, "%s\n", Inv_t_name[*ip]);
359 return NORM;
360}
361
362
363#ifdef MASTER
364/*
365 * get_num:
366 * Get a numeric option
367 */
368int
369get_num(void *vp, WINDOW *win)
370{
371 short *opt = (short *) vp;
372 int i;
373 static char buf[MAXSTR];
374
375 if ((i = get_str(buf, win)) == NORM)
376 *opt = atoi(buf);
377 return i;
378}
379#endif
380
381/*
382 * parse_opts:
383 * Parse options from string, usually taken from the environment.
384 * The string is a series of comma seperated values, with booleans
385 * being stated as "name" (true) or "noname" (false), and strings
386 * being "name=....", with the string being defined up to a comma
387 * or the end of the entire option string.
388 */
389void
390parse_opts(char *str)
391{
392 char *sp;
393 OPTION *op;
394 int len;
395 char **i;
396 char *start;
397
398 while (*str)
399 {
400 /*
401 * Get option name
402 */
403 for (sp = str; isalpha(*sp); sp++)
404 continue;
405 len = sp - str;
406 /*
407 * Look it up and deal with it
408 */
409 for (op = optlist; op < &optlist[NUM_OPTS]; op++)
410 if (EQSTR(str, op->o_name, len))
411 {
412 if (op->o_putfunc == put_bool) /* if option is a boolean */
413 *(bool *)op->o_opt = TRUE; /* NOSTRICT */
414 else /* string option */
415 {
416 /*
417 * Skip to start of string value
418 */
419 for (str = sp + 1; *str == '='; str++)
420 continue;
421 if (*str == '~')
422 {
423 strcpy((char *) op->o_opt, Home); /* NOSTRICT */
424 start = (char *) op->o_opt + strlen(Home);/* NOSTRICT */
425 while (*++str == '/')
426 continue;
427 }
428 else
429 start = (char *) op->o_opt; /* NOSTRICT */
430 /*
431 * Skip to end of string value
432 */
433 for (sp = str + 1; *sp && *sp != ','; sp++)
434 continue;
435 /*
436 * check for type of inventory
437 */
438 if (op->o_putfunc == put_inv_t)
439 {
440 if (islower(*str))
441 *str = toupper(*str);
442 for (i = Inv_t_name; i <= &Inv_t_name[INV_CLEAR]; i++)
443 if (strncmp(str, *i, sp - str) == 0)
444 {
445 Inv_type = i - Inv_t_name;
446 break;
447 }
448 }
449 else
450 strucpy(start, str, sp - str);
451 }
452 break;
453 }
454 /*
455 * check for "noname" for booleans
456 */
457 else if (op->o_putfunc == put_bool
458 && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
459 {
460 *(bool *)op->o_opt = FALSE; /* NOSTRICT */
461 break;
462 }
463
464 /*
465 * skip to start of next option name
466 */
467 while (*sp && !isalpha(*sp))
468 sp++;
469 str = sp;
470 }
471}
472
473/*
474 * strucpy:
475 * Copy string using unctrl for things
476 */
477void
478strucpy(char *s1, char *s2, int len)
479{
480 if (len > MAXINP)
481 len = MAXINP;
482 while (len--)
483 {
484 if (isprint(*s2) || *s2 == ' ')
485 *s1++ = *s2;
486 s2++;
487 }
488 *s1 = '\0';
489}