rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

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}