2 * io.c - input/output routines for Phantasia
4 * $FreeBSD: src/games/phantasia/io.c,v 1.6 1999/11/16 02:57:33 billf Exp $
5 * $DragonFly: src/games/phantasia/io.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
11 /************************************************************************
13 / FUNCTION NAME: getstring()
15 / FUNCTION: read a string from operator
17 / AUTHOR: E. A. Estes, 12/4/85
20 / char *cp - pointer to buffer area to fill
21 / int mx - maximum number of characters to put in buffer
25 / MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
28 / GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
30 / GLOBAL OUTPUTS: _iob[]
33 / Read a string from the keyboard.
34 / This routine is specially designed to:
36 / - strip non-printing characters (unless Wizard)
38 / - redraw the screen if CH_REDRAW is entered
39 / - read in only 'mx - 1' characters or less characters
40 / - nul-terminate string, and throw away newline
42 / 'mx' is assumed to be at least 2.
44 *************************************************************************/
50 char *inptr; /* pointer into string for next string */
51 int x, y; /* original x, y coordinates on screen */
54 getyx(stdscr, y, x); /* get coordinates on screen */
56 *inptr = '\0'; /* clear string to start */
57 --mx; /* reserve room in string for nul terminator */
60 /* get characters and process */
63 mvaddstr(y, x, cp); /* print string on screen */
64 clrtoeol(); /* clear any data after string */
65 refresh(); /* update screen */
67 ch = getchar(); /* get character */
71 case CH_ERASE: /* back up one character */
76 case CH_KILL: /* back up to original location */
80 case CH_NEWLINE: /* terminate string */
83 case CH_REDRAW: /* redraw screen */
84 clearok(stdscr, TRUE);
87 default: /* put data in string */
88 if (ch >= ' ' || Wizard)
89 /* printing char; put in string */
93 *inptr = '\0'; /* terminate string */
95 while (ch != CH_NEWLINE && inptr < cp + mx);
98 /************************************************************************
100 / FUNCTION NAME: more()
102 / FUNCTION: pause and prompt player
104 / AUTHOR: E. A. Estes, 12/4/85
107 / int where - line on screen on which to pause
111 / MODULES CALLED: wmove(), waddstr(), getanswer()
113 / GLOBAL INPUTS: *stdscr
115 / GLOBAL OUTPUTS: none
118 / Print a message, and wait for a space character.
120 *************************************************************************/
125 mvaddstr(where, 0, "-- more --");
126 getanswer(" ", FALSE);
129 /************************************************************************
131 / FUNCTION NAME: infloat()
133 / FUNCTION: input a floating point number from operator
135 / AUTHOR: E. A. Estes, 12/4/85
139 / RETURN VALUE: floating point number from operator
141 / MODULES CALLED: sscanf(), getstring()
143 / GLOBAL INPUTS: Databuf[]
145 / GLOBAL OUTPUTS: none
148 / Read a string from player, and scan for a floating point
150 / If no valid number is found, return 0.0.
152 *************************************************************************/
157 double result; /* return value */
159 getstring(Databuf, SZ_DATABUF);
160 if (sscanf(Databuf, "%lf", &result) < 1)
161 /* no valid number entered */
167 /************************************************************************
169 / FUNCTION NAME: inputoption()
171 / FUNCTION: input an option value from player
173 / AUTHOR: E. A. Estes, 12/4/85
179 / MODULES CALLED: floor(), drandom(), getanswer()
181 / GLOBAL INPUTS: Player
183 / GLOBAL OUTPUTS: Player
186 / Age increases with every move.
187 / Refresh screen, and get a single character option from player.
188 / Return a random value if player's ring has gone bad.
190 *************************************************************************/
194 ++Player.p_age; /* increase age */
196 if (Player.p_ring.ring_type != R_SPOILED)
198 return(getanswer("T ", TRUE));
202 getanswer(" ", TRUE);
203 return((int) ROLL(0.0, 5.0) + '0');
207 /************************************************************************
209 / FUNCTION NAME: interrupt()
211 / FUNCTION: handle interrupt from operator
213 / AUTHOR: E. A. Estes, 12/4/85
219 / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
220 / getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
221 / crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
224 / GLOBAL INPUTS: Player, *stdscr
226 / GLOBAL OUTPUTS: none
229 / Allow player to quit upon hitting the interrupt key.
230 / If the player wants to quit while in battle, he/she automatically
233 *************************************************************************/
237 char line[81]; /* a place to store data already on screen */
238 int loop; /* counter */
239 int x, y; /* coordinates on screen */
241 unsigned savealarm; /* to save alarm value */
244 signal(SIGINT, SIG_IGN);
247 signal(SIGINT, SIG_IGN);
250 savealarm = alarm(0); /* turn off any alarms */
252 getyx(stdscr, y, x); /* save cursor location */
254 for (loop = 0; loop < 80; ++loop) /* save line on screen */
259 line[80] = '\0'; /* nul terminate */
261 if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
262 /* in midst of fighting */
264 mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
265 ch = getanswer("NY", FALSE);
267 death("Bailing out");
272 mvaddstr(4, 0, "Do you really want to quit ? ");
273 ch = getanswer("NY", FALSE);
279 mvaddstr(4, 0, line); /* restore data on screen */
280 move(y, x); /* restore cursor */
284 signal(SIGINT, interrupt);
287 signal(SIGINT, interrupt);
290 alarm(savealarm); /* restore alarm */
293 /************************************************************************
295 / FUNCTION NAME: getanswer()
297 / FUNCTION: get an answer from operator
299 / AUTHOR: E. A. Estes, 12/4/85
302 / char *choices - string of (upper case) valid choices
303 / bool def - set if default answer
307 / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
308 / _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
310 / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
313 / GLOBAL OUTPUTS: _iob[]
316 / Get a single character answer from operator.
317 / Timeout waiting for response. If we timeout, or the
318 / answer in not in the list of valid choices, print choices,
319 / and wait again, otherwise return the first character in ths
321 / Give up after 3 tries.
323 *************************************************************************/
325 getanswer(choices, def)
330 int loop; /* counter */
331 int oldx, oldy; /* original coordinates on screen */
333 getyx(stdscr, oldy, oldx);
334 alarm(0); /* make sure alarm is off */
336 for (loop = 3; loop; --loop)
337 /* try for 3 times */
339 if (setjmp(Timeoenv) != 0)
340 /* timed out waiting for response */
342 if (def || loop <= 1)
343 /* return default answer */
346 /* prompt, and try again */
350 /* wait for response */
355 sigset(SIGALRM, catchalarm);
357 signal(SIGALRM, catchalarm);
361 alarm(7); /* short */
363 alarm(600); /* long */
367 alarm(0); /* turn off timeout */
370 /* caught some signal */
375 else if (ch == CH_REDRAW)
378 clearok(stdscr, TRUE); /* force clear screen */
379 ++loop; /* don't count this input */
384 addch(ch); /* echo character */
389 /* convert to upper case */
392 if (def || strchr(choices, ch) != NULL)
395 else if (!def && loop > 1)
396 /* bad choice; prompt, and try again */
398 YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
404 /* return default answer */
412 /************************************************************************
414 / FUNCTION NAME: catchalarm()
416 / FUNCTION: catch timer when waiting for input
418 / AUTHOR: E. A. Estes, 12/4/85
424 / MODULES CALLED: longjmp()
426 / GLOBAL INPUTS: Timeoenv[]
428 / GLOBAL OUTPUTS: none
431 / Come here when the alarm expires while waiting for input.
432 / Simply longjmp() into getanswer().
434 *************************************************************************/
439 longjmp(Timeoenv, 1);