1/* $NetBSD: io.c,v 1.13 2009/08/12 08:21:41 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 26static void catchalarm(int) __dead; 27 28void 29getstring(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 78void 79more(int where) 80{ 81 mvaddstr(where, 0, "-- more --"); 82 getanswer(" ", FALSE); 83} 84 85double 86infloat(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 98int 99inputoption(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 114void 115interrupt(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 170int 171getanswer(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 253static void 254catchalarm(int dummy __unused) 255{ 256 longjmp(Timeoenv, 1); 257} 258