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 <sys/cdefs.h> 8 9 #include <ctype.h> 10 #include <math.h> 11 #include <setjmp.h> 12 #include <signal.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include "macros.h" 18 #include "phantdefs.h" 19 #include "phantstruct.h" 20 #include "phantglobs.h" 21 //#include "pathnames.h" 22 23 #undef bool 24 #include <curses.h> 25 26 static void catchalarm(int) __dead; 27 28 void 29 getstring(char *cp, int mx) 30 { 31 char *inptr; /* pointer into string for next string */ 32 int x, y; /* original x, y coordinates on screen */ 33 int ch; /* input */ 34 35 getyx(stdscr, y, x); /* get coordinates on screen */ 36 inptr = cp; 37 *inptr = '\0'; /* clear string to start */ 38 --mx; /* reserve room in string for nul terminator */ 39 40 do 41 /* get characters and process */ 42 { 43 if (Echo) 44 mvaddstr(y, x, cp); /* print string on screen */ 45 clrtoeol(); /* clear any data after string */ 46 refresh(); /* update screen */ 47 48 ch = getchar(); /* get character */ 49 50 switch (ch) { 51 case CH_ERASE: /* back up one character */ 52 if (inptr > cp) 53 --inptr; 54 break; 55 56 case CH_KILL: /* back up to original location */ 57 inptr = cp; 58 break; 59 60 case CH_NEWLINE: /* terminate string */ 61 break; 62 63 case CH_REDRAW:/* redraw screen */ 64 clearok(stdscr, TRUE); 65 continue; 66 67 default: /* put data in string */ 68 if (ch >= ' ' || Wizard) 69 /* printing char; put in string */ 70 *inptr++ = ch; 71 } 72 73 *inptr = '\0'; /* terminate string */ 74 } 75 while (ch != CH_NEWLINE && inptr < cp + mx); 76 } 77 78 void 79 more(int where) 80 { 81 mvaddstr(where, 0, "-- more --"); 82 getanswer(" ", FALSE); 83 } 84 85 double 86 infloat(void) 87 { 88 double result; /* return value */ 89 90 getstring(Databuf, SZ_DATABUF); 91 if (sscanf(Databuf, "%lf", &result) < 1) 92 /* no valid number entered */ 93 result = 0.0; 94 95 return (result); 96 } 97 98 int 99 inputoption(void) 100 { 101 ++Player.p_age; /* increase age */ 102 103 if (Player.p_ring.ring_type != R_SPOILED) 104 /* ring ok */ 105 return (getanswer("T ", TRUE)); 106 else 107 /* bad ring */ 108 { 109 getanswer(" ", TRUE); 110 return ((int) ROLL(0.0, 5.0) + '0'); 111 } 112 } 113 114 void 115 interrupt(void) 116 { 117 char line[81]; /* a place to store data already on screen */ 118 int loop; /* counter */ 119 int x, y; /* coordinates on screen */ 120 int ch; /* input */ 121 unsigned savealarm; /* to save alarm value */ 122 123 #ifdef SYS3 124 signal(SIGINT, SIG_IGN); 125 #endif 126 #ifdef SYS5 127 signal(SIGINT, SIG_IGN); 128 #endif 129 130 savealarm = alarm(0); /* turn off any alarms */ 131 132 getyx(stdscr, y, x); /* save cursor location */ 133 134 for (loop = 0; loop < 80; ++loop) { /* save line on screen */ 135 move(4, loop); 136 line[loop] = inch(); 137 } 138 line[80] = '\0'; /* nul terminate */ 139 140 if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER) 141 /* in midst of fighting */ 142 { 143 mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? "); 144 ch = getanswer("NY", FALSE); 145 if (ch == 'Y') 146 death("Bailing out"); 147 /* NOTREACHED */ 148 } else { 149 mvaddstr(4, 0, "Do you really want to quit ? "); 150 ch = getanswer("NY", FALSE); 151 if (ch == 'Y') 152 leavegame(); 153 /* NOTREACHED */ 154 } 155 156 mvaddstr(4, 0, line); /* restore data on screen */ 157 move(y, x); /* restore cursor */ 158 refresh(); 159 160 #ifdef SYS3 161 signal(SIGINT, interrupt); 162 #endif 163 #ifdef SYS5 164 signal(SIGINT, interrupt); 165 #endif 166 167 alarm(savealarm); /* restore alarm */ 168 } 169 170 int 171 getanswer(const char *choices, phbool def) 172 { 173 int ch; /* input */ 174 volatile int loop; /* counter */ 175 volatile int oldx, oldy; /* original coordinates on screen */ 176 177 getyx(stdscr, oldy, oldx); 178 alarm(0); /* make sure alarm is off */ 179 180 for (loop = 3; loop; --loop) 181 /* try for 3 times */ 182 { 183 if (setjmp(Timeoenv) != 0) 184 /* timed out waiting for response */ 185 { 186 if (def || loop <= 1) 187 /* return default answer */ 188 break; 189 else 190 /* prompt, and try again */ 191 goto YELL; 192 } else 193 /* wait for response */ 194 { 195 clrtoeol(); 196 refresh(); 197 #ifdef BSD41 198 sigset(SIGALRM, catchalarm); 199 #else 200 signal(SIGALRM, catchalarm); 201 #endif 202 /* set timeout */ 203 if (Timeout) 204 alarm(7); /* short */ 205 else 206 alarm(600); /* long */ 207 208 ch = getchar(); 209 210 alarm(0); /* turn off timeout */ 211 212 if (ch < 0) 213 /* caught some signal */ 214 { 215 ++loop; 216 continue; 217 } else 218 if (ch == CH_REDRAW) 219 /* redraw screen */ 220 { 221 clearok(stdscr, TRUE); /* force clear screen */ 222 ++loop; /* don't count this input */ 223 continue; 224 } else 225 if (Echo) { 226 addch(ch); /* echo character */ 227 refresh(); 228 } 229 if (islower(ch)) 230 /* convert to upper case */ 231 ch = toupper(ch); 232 233 if (def || strchr(choices, ch) != NULL) 234 /* valid choice */ 235 return (ch); 236 else 237 if (!def && loop > 1) 238 /* bad choice; prompt, and try again */ 239 { 240 YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices); 241 move(oldy, oldx); 242 clrtoeol(); 243 continue; 244 } else 245 /* return default answer */ 246 break; 247 } 248 } 249 250 return (*choices); 251 } 252 253 static void 254 catchalarm(int dummy __unused) 255 { 256 longjmp(Timeoenv, 1); 257 } 258