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