drm: Pass CRTC ID in userspace vblank events
[dragonfly.git] / games / phantasia / io.c
1 /*      $NetBSD: io.c,v 1.14 2009/08/31 08:27:16 dholland Exp $ */
2
3 /*
4  * io.c - input/output routines for Phantasia
5  */
6
7 #include <string.h>
8 #include "include.h"
9
10 static void catchalarm(int) __dead2;
11
12 /*
13  * FUNCTION: read a string from operator
14  *
15  * ARGUMENTS:
16  *      char *cp - pointer to buffer area to fill
17  *      int mx - maximum number of characters to put in buffer
18  *
19  * GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
20  *
21  * GLOBAL OUTPUTS: _iob[]
22  *
23  * DESCRIPTION:
24  *      Read a string from the keyboard.
25  *      This routine is specially designed to:
26  *
27  *          - strip non-printing characters (unless Wizard)
28  *          - echo, if desired
29  *          - redraw the screen if CH_REDRAW is entered
30  *          - read in only 'mx - 1' characters or less characters
31  *          - nul-terminate string, and throw away newline
32  *
33  *      'mx' is assumed to be at least 2.
34  */
35
36 void
37 getstring(char *cp, int mx)
38 {
39         char *inptr;            /* pointer into string for next string */
40         int x, y;               /* original x, y coordinates on screen */
41         int ch;                 /* input */
42
43         getyx(stdscr, y, x);    /* get coordinates on screen */
44         inptr = cp;
45         *inptr = '\0';          /* clear string to start */
46         --mx;                   /* reserve room in string for nul terminator */
47
48         do {
49                 /* get characters and process */
50                 if (Echo)
51                         mvaddstr(y, x, cp);     /* print string on screen */
52                 clrtoeol();     /* clear any data after string */
53                 refresh();      /* update screen */
54
55                 ch = getchar(); /* get character */
56
57                 switch (ch) {
58                 case CH_ERASE:  /* back up one character */
59                         if (inptr > cp)
60                                 --inptr;
61                         break;
62
63                 case CH_KILL:   /* back up to original location */
64                         inptr = cp;
65                         break;
66
67                 case CH_NEWLINE:        /* terminate string */
68                         break;
69
70                 case CH_REDRAW: /* redraw screen */
71                         clearok(stdscr, TRUE);
72                         continue;
73
74                 default:        /* put data in string */
75                         if (ch >= ' ' || Wizard)
76                                 /* printing char; put in string */
77                                 *inptr++ = ch;
78                 }
79
80                 *inptr = '\0';  /* terminate string */
81         } while (ch != CH_NEWLINE && inptr < cp + mx);
82 }
83
84 /*
85  * FUNCTION: pause and prompt player
86  *
87  * ARGUMENTS:
88  *      int where - line on screen on which to pause
89  *
90  * GLOBAL INPUTS: *stdscr
91  *
92  * DESCRIPTION:
93  *      Print a message, and wait for a space character.
94  */
95
96 void
97 more(int where)
98 {
99         mvaddstr(where, 0, "-- more --");
100         getanswer(" ", FALSE);
101 }
102
103 /*
104  * FUNCTION: input a floating point number from operator
105  *
106  * RETURN VALUE: floating point number from operator
107  *
108  * GLOBAL INPUTS: Databuf[]
109  *
110  * DESCRIPTION:
111  *      Read a string from player, and scan for a floating point
112  *      number.
113  *      If no valid number is found, return 0.0.
114  */
115
116 double
117 infloat(void)
118 {
119         double result;          /* return value */
120
121         getstring(Databuf, SZ_DATABUF);
122         if (sscanf(Databuf, "%lf", &result) < 1)
123                 /* no valid number entered */
124                 result = 0.0;
125
126         return (result);
127 }
128
129 /*
130  * FUNCTION: input an option value from player
131  *
132  * GLOBAL INPUTS: Player
133  *
134  * GLOBAL OUTPUTS: Player
135  *
136  * DESCRIPTION:
137  *      Age increases with every move.
138  *      Refresh screen, and get a single character option from player.
139  *      Return a random value if player's ring has gone bad.
140  */
141
142 int
143 inputoption(void)
144 {
145         ++Player.p_age;         /* increase age */
146
147         if (Player.p_ring.ring_type != R_SPOILED)
148                 /* ring ok */
149                 return (getanswer("T ", TRUE));
150         else {
151                 /* bad ring */
152                 getanswer(" ", TRUE);
153                 return ((int)ROLL(0.0, 5.0) + '0');
154         }
155 }
156
157 /*
158  * FUNCTION: handle interrupt from operator
159  *
160  * GLOBAL INPUTS: Player, *stdscr
161  *
162  * DESCRIPTION:
163  *      Allow player to quit upon hitting the interrupt key.
164  *      If the player wants to quit while in battle, he/she automatically
165  *      dies.
166  */
167
168 void
169 interrupt(void)
170 {
171         char line[81];          /* a place to store data already on screen */
172         int loop;               /* counter */
173         int x, y;               /* coordinates on screen */
174         int ch;                 /* input */
175         unsigned savealarm;     /* to save alarm value */
176
177 #ifdef SYS3
178         signal(SIGINT, SIG_IGN);
179 #endif
180 #ifdef SYS5
181         signal(SIGINT, SIG_IGN);
182 #endif
183
184         savealarm = alarm(0);   /* turn off any alarms */
185
186         getyx(stdscr, y, x);    /* save cursor location */
187
188         for (loop = 0; loop < 80; ++loop) {     /* save line on screen */
189                 move(4, loop);
190                 line[loop] = inch();
191         }
192         line[80] = '\0';        /* nul terminate */
193
194         if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER) {
195                 /* in midst of fighting */
196                 mvaddstr(4, 0, "Quitting now will automatically kill your character.  Still want to ? ");
197                 ch = getanswer("NY", FALSE);
198                 if (ch == 'Y')
199                         death("Bailing out");
200                 /* NOTREACHED */
201         } else {
202                 mvaddstr(4, 0, "Do you really want to quit ? ");
203                 ch = getanswer("NY", FALSE);
204                 if (ch == 'Y')
205                         leavegame();
206                 /* NOTREACHED */
207         }
208
209         mvaddstr(4, 0, line);   /* restore data on screen */
210         move(y, x);             /* restore cursor */
211         refresh();
212
213 #ifdef SYS3
214         signal(SIGINT, interrupt);
215 #endif
216 #ifdef SYS5
217         signal(SIGINT, interrupt);
218 #endif
219
220         alarm(savealarm);       /* restore alarm */
221 }
222
223 /*
224  * FUNCTION: get an answer from operator
225  *
226  * ARGUMENTS:
227  *      char *choices - string of (upper case) valid choices
228  *      bool def - set if default answer
229  *
230  * GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
231  *      Timeoenv[]
232  *
233  * GLOBAL OUTPUTS: _iob[]
234  *
235  * DESCRIPTION:
236  *      Get a single character answer from operator.
237  *      Timeout waiting for response.  If we timeout, or the
238  *      answer in not in the list of valid choices, print choices,
239  *      and wait again, otherwise return the first character in ths
240  *      list of choices.
241  *      Give up after 3 tries.
242  */
243
244 int
245 getanswer(const char *choices, bool def)
246 {
247         int ch;                         /* input */
248         volatile int loop;              /* counter */
249         volatile int oldx, oldy;        /* original coordinates on screen */
250
251         getyx(stdscr, oldy, oldx);
252         alarm(0);                       /* make sure alarm is off */
253
254         for (loop = 3; loop; --loop) {
255                 /* try for 3 times */
256                 if (setjmp(Timeoenv) != 0) {
257                         /* timed out waiting for response */
258                         if (def || loop <= 1)
259                                 /* return default answer */
260                                 break;
261                         else
262                                 /* prompt, and try again */
263                                 goto YELL;
264                 } else {
265                         /* wait for response */
266                         clrtoeol();
267                         refresh();
268 #ifdef BSD41
269                         sigset(SIGALRM, catchalarm);
270 #else
271                         signal(SIGALRM, catchalarm);
272 #endif
273                         /* set timeout */
274                         if (Timeout)
275                                 alarm(7);       /* short */
276                         else
277                                 alarm(600);     /* long */
278
279                         ch = getchar();
280
281                         alarm(0);       /* turn off timeout */
282
283                         if (ch < 0) {
284                                 /* caught some signal */
285                                 ++loop;
286                                 continue;
287                         } else if (ch == CH_REDRAW) {
288                                 /* redraw screen */
289                                 clearok(stdscr, TRUE);  /* force clear screen */
290                                 ++loop; /* don't count this input */
291                                 continue;
292                         } else if (Echo) {
293                                 addch(ch);      /* echo character */
294                                 refresh();
295                         }
296
297                         if (islower(ch))
298                                 /* convert to upper case */
299                                 ch = toupper(ch);
300
301                         if (def || strchr(choices, ch) != NULL)
302                                 /* valid choice */
303                                 return (ch);
304                         else if (!def && loop > 1) {
305                                 /* bad choice; prompt, and try again */
306 YELL:                           mvprintw(oldy + 1, 0,
307                                     "Please choose one of : [%s]\n", choices);
308                                 move(oldy, oldx);
309                                 clrtoeol();
310                                 continue;
311                         } else
312                                 /* return default answer */
313                                 break;
314                 }
315         }
316
317         return (*choices);
318 }
319
320 /*
321  * FUNCTION: catch timer when waiting for input
322  *
323  * GLOBAL INPUTS: Timeoenv[]
324  *
325  * DESCRIPTION:
326  *      Come here when the alarm expires while waiting for input.
327  *      Simply longjmp() into getanswer().
328  */
329
330 static void
331 catchalarm(__unused int sig)
332 {
333         longjmp(Timeoenv, 1);
334 }