|
|
1.1 ! root 1: /* ! 2: * io.c - input/output routines for Phantasia ! 3: */ ! 4: ! 5: #include "include.h" ! 6: ! 7: /************************************************************************ ! 8: / ! 9: / FUNCTION NAME: getstring() ! 10: / ! 11: / FUNCTION: read a string from operator ! 12: / ! 13: / AUTHOR: E. A. Estes, 12/4/85 ! 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: / RETURN VALUE: none ! 20: / ! 21: / MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(), ! 22: / wclrtoeol() ! 23: / ! 24: / GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr ! 25: / ! 26: / GLOBAL OUTPUTS: _iob[] ! 27: / ! 28: / DESCRIPTION: ! 29: / Read a string from the keyboard. ! 30: / This routine is specially designed to: ! 31: / ! 32: / - strip non-printing characters (unless Wizard) ! 33: / - echo, if desired ! 34: / - redraw the screen if CH_REDRAW is entered ! 35: / - read in only 'mx - 1' characters or less characters ! 36: / - nul-terminate string, and throw away newline ! 37: / ! 38: / 'mx' is assumed to be at least 2. ! 39: / ! 40: /************************************************************************/ ! 41: ! 42: getstring(cp, mx) ! 43: register char *cp; ! 44: register int mx; ! 45: { ! 46: register char *inptr; /* pointer into string for next string */ ! 47: int x, y; /* original x, y coordinates on screen */ ! 48: int ch; /* input */ ! 49: ! 50: getyx(stdscr, y, x); /* get coordinates on screen */ ! 51: inptr = cp; ! 52: *inptr = '\0'; /* clear string to start */ ! 53: --mx; /* reserve room in string for nul terminator */ ! 54: ! 55: do ! 56: /* get characters and process */ ! 57: { ! 58: if (Echo) ! 59: mvaddstr(y, x, cp); /* print string on screen */ ! 60: clrtoeol(); /* clear any data after string */ ! 61: refresh(); /* update screen */ ! 62: ! 63: ch = getchar(); /* get character */ ! 64: ! 65: switch (ch) ! 66: { ! 67: case CH_ERASE: /* back up one character */ ! 68: if (inptr > cp) ! 69: --inptr; ! 70: break; ! 71: ! 72: case CH_KILL: /* back up to original location */ ! 73: inptr = cp; ! 74: break; ! 75: ! 76: case CH_NEWLINE: /* terminate string */ ! 77: break; ! 78: ! 79: case CH_REDRAW: /* redraw screen */ ! 80: clearok(stdscr, TRUE); ! 81: continue; ! 82: ! 83: default: /* put data in string */ ! 84: if (ch >= ' ' || Wizard) ! 85: /* printing char; put in string */ ! 86: *inptr++ = ch; ! 87: } ! 88: ! 89: *inptr = '\0'; /* terminate string */ ! 90: } ! 91: while (ch != CH_NEWLINE && inptr < cp + mx); ! 92: } ! 93: /**/ ! 94: /************************************************************************ ! 95: / ! 96: / FUNCTION NAME: more() ! 97: / ! 98: / FUNCTION: pause and prompt player ! 99: / ! 100: / AUTHOR: E. A. Estes, 12/4/85 ! 101: / ! 102: / ARGUMENTS: ! 103: / int where - line on screen on which to pause ! 104: / ! 105: / RETURN VALUE: none ! 106: / ! 107: / MODULES CALLED: wmove(), waddstr(), getanswer() ! 108: / ! 109: / GLOBAL INPUTS: *stdscr ! 110: / ! 111: / GLOBAL OUTPUTS: none ! 112: / ! 113: / DESCRIPTION: ! 114: / Print a message, and wait for a space character. ! 115: / ! 116: /************************************************************************/ ! 117: ! 118: more(where) ! 119: int where; ! 120: { ! 121: mvaddstr(where, 0, "-- more --"); ! 122: getanswer(" ", FALSE); ! 123: } ! 124: /**/ ! 125: /************************************************************************ ! 126: / ! 127: / FUNCTION NAME: infloat() ! 128: / ! 129: / FUNCTION: input a floating point number from operator ! 130: / ! 131: / AUTHOR: E. A. Estes, 12/4/85 ! 132: / ! 133: / ARGUMENTS: none ! 134: / ! 135: / RETURN VALUE: floating point number from operator ! 136: / ! 137: / MODULES CALLED: sscanf(), getstring() ! 138: / ! 139: / GLOBAL INPUTS: Databuf[] ! 140: / ! 141: / GLOBAL OUTPUTS: none ! 142: / ! 143: / DESCRIPTION: ! 144: / Read a string from player, and scan for a floating point ! 145: / number. ! 146: / If no valid number is found, return 0.0. ! 147: / ! 148: /************************************************************************/ ! 149: ! 150: double ! 151: infloat() ! 152: { ! 153: double result; /* return value */ ! 154: ! 155: getstring(Databuf, SZ_DATABUF); ! 156: if (sscanf(Databuf, "%lf", &result) < 1) ! 157: /* no valid number entered */ ! 158: result = 0.0; ! 159: ! 160: return(result); ! 161: } ! 162: /**/ ! 163: /************************************************************************ ! 164: / ! 165: / FUNCTION NAME: inputoption() ! 166: / ! 167: / FUNCTION: input an option value from player ! 168: / ! 169: / AUTHOR: E. A. Estes, 12/4/85 ! 170: / ! 171: / ARGUMENTS: none ! 172: / ! 173: / RETURN VALUE: none ! 174: / ! 175: / MODULES CALLED: floor(), drandom(), getanswer() ! 176: / ! 177: / GLOBAL INPUTS: Player ! 178: / ! 179: / GLOBAL OUTPUTS: Player ! 180: / ! 181: / DESCRIPTION: ! 182: / Age increases with every move. ! 183: / Refresh screen, and get a single character option from player. ! 184: / Return a random value if player's ring has gone bad. ! 185: / ! 186: /************************************************************************/ ! 187: ! 188: inputoption() ! 189: { ! 190: ++Player.p_age; /* increase age */ ! 191: ! 192: if (Player.p_ring.ring_type != R_SPOILED) ! 193: /* ring ok */ ! 194: return(getanswer("T ", TRUE)); ! 195: else ! 196: /* bad ring */ ! 197: { ! 198: getanswer(" ", TRUE); ! 199: return((int) ROLL(0.0, 5.0) + '0'); ! 200: } ! 201: } ! 202: /**/ ! 203: /************************************************************************ ! 204: / ! 205: / FUNCTION NAME: interrupt() ! 206: / ! 207: / FUNCTION: handle interrupt from operator ! 208: / ! 209: / AUTHOR: E. A. Estes, 12/4/85 ! 210: / ! 211: / ARGUMENTS: none ! 212: / ! 213: / RETURN VALUE: none ! 214: / ! 215: / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(), ! 216: / getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(), ! 217: / crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(), ! 218: / getanswer() ! 219: / ! 220: / GLOBAL INPUTS: Player, *stdscr ! 221: / ! 222: / GLOBAL OUTPUTS: none ! 223: / ! 224: / DESCRIPTION: ! 225: / Allow player to quit upon hitting the interrupt key. ! 226: / If the player wants to quit while in battle, he/she automatically ! 227: / dies. ! 228: / If SHELL is defined, spawn a shell if the if the question is ! 229: / answered with a '!'. ! 230: / We are careful to save the state of the screen, and return it ! 231: / to its original condition. ! 232: / ! 233: /************************************************************************/ ! 234: ! 235: interrupt() ! 236: { ! 237: char line[81]; /* a place to store data already on screen */ ! 238: register int loop; /* counter */ ! 239: int x, y; /* coordinates on screen */ ! 240: int ch; /* input */ ! 241: unsigned savealarm; /* to save alarm value */ ! 242: #ifdef SHELL ! 243: register char *shell; /* pointer to shell to spawn */ ! 244: int childpid; /* pid of spawned process */ ! 245: #endif ! 246: ! 247: #ifdef SYS3 ! 248: signal(SIGINT, SIG_IGN); ! 249: #endif ! 250: #ifdef SYS5 ! 251: signal(SIGINT, SIG_IGN); ! 252: #endif ! 253: ! 254: savealarm = alarm(0); /* turn off any alarms */ ! 255: ! 256: getyx(stdscr, y, x); /* save cursor location */ ! 257: ! 258: for (loop = 0; loop < 80; ++loop) /* save line on screen */ ! 259: { ! 260: move(4, loop); ! 261: line[loop] = inch(); ! 262: } ! 263: line[80] = '\0'; /* nul terminate */ ! 264: ! 265: if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER) ! 266: /* in midst of fighting */ ! 267: { ! 268: mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? "); ! 269: #ifdef SHELL ! 270: ch = getanswer("NY!", FALSE); ! 271: #else ! 272: ch = getanswer("NY", FALSE); ! 273: #endif ! 274: if (ch == 'Y') ! 275: death("Bailing out"); ! 276: /*NOTREACHED*/ ! 277: } ! 278: else ! 279: { ! 280: #ifdef SHELL ! 281: mvaddstr(4, 0, "Do you really want to quit [! = Shell] ? "); ! 282: ch = getanswer("NY!", FALSE); ! 283: #else ! 284: mvaddstr(4, 0, "Do you really want to quit ? "); ! 285: ch = getanswer("NY", FALSE); ! 286: #endif ! 287: if (ch == 'Y') ! 288: leavegame(); ! 289: /*NOTREACHED*/ ! 290: } ! 291: ! 292: #ifdef SHELL ! 293: if (ch == '!') ! 294: /* shell escape */ ! 295: { ! 296: if ((shell = getenv("SHELL")) == NULL) ! 297: /* use default */ ! 298: shell = SHELL; ! 299: ! 300: if ((childpid = fork()) == 0) ! 301: /* in child */ ! 302: { ! 303: clear(); ! 304: refresh(); ! 305: cleanup(FALSE); /* out of curses, close files */ ! 306: ! 307: setuid(getuid()); /* make sure we are running with real uid */ ! 308: setgid(getgid()); /* make sure we are running with real gid */ ! 309: execl(shell, shell, "-i", 0); ! 310: execl(SHELL, SHELL, "-i", 0); /* last resort */ ! 311: ! 312: exit(0); ! 313: /*NOTREACHED*/ ! 314: } ! 315: else ! 316: /* in parent */ ! 317: { ! 318: while (wait((int *) NULL) != childpid); /* wait until done */ ! 319: crmode(); /* restore keyboard */ ! 320: clearok(stdscr, TRUE); /* force redraw of screen */ ! 321: } ! 322: } ! 323: #endif ! 324: ! 325: mvaddstr(4, 0, line); /* restore data on screen */ ! 326: move(y, x); /* restore cursor */ ! 327: refresh(); ! 328: ! 329: #ifdef SYS3 ! 330: signal(SIGINT, interrupt); ! 331: #endif ! 332: #ifdef SYS5 ! 333: signal(SIGINT, interrupt); ! 334: #endif ! 335: ! 336: alarm(savealarm); /* restore alarm */ ! 337: } ! 338: /**/ ! 339: /************************************************************************ ! 340: / ! 341: / FUNCTION NAME: getanswer() ! 342: / ! 343: / FUNCTION: get an answer from operator ! 344: / ! 345: / AUTHOR: E. A. Estes, 12/4/85 ! 346: / ! 347: / ARGUMENTS: ! 348: / char *choices - string of (upper case) valid choices ! 349: / bool def - set if default answer ! 350: / ! 351: / RETURN VALUE: none ! 352: / ! 353: / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(), ! 354: / _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol() ! 355: / ! 356: / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout, ! 357: / Timeoenv[] ! 358: / ! 359: / GLOBAL OUTPUTS: _iob[] ! 360: / ! 361: / DESCRIPTION: ! 362: / Get a single character answer from operator. ! 363: / Timeout waiting for response. If we timeout, or the ! 364: / answer in not in the list of valid choices, print choices, ! 365: / and wait again, otherwise return the first character in ths ! 366: / list of choices. ! 367: / Give up after 3 tries. ! 368: / ! 369: /************************************************************************/ ! 370: ! 371: getanswer(choices, def) ! 372: char *choices; ! 373: bool def; ! 374: { ! 375: int ch; /* input */ ! 376: int loop; /* counter */ ! 377: int oldx, oldy; /* original coordinates on screen */ ! 378: ! 379: getyx(stdscr, oldy, oldx); ! 380: alarm(0); /* make sure alarm is off */ ! 381: ! 382: for (loop = 3; loop; --loop) ! 383: /* try for 3 times */ ! 384: { ! 385: if (setjmp(Timeoenv) != 0) ! 386: /* timed out waiting for response */ ! 387: { ! 388: if (def || loop <= 1) ! 389: /* return default answer */ ! 390: break; ! 391: else ! 392: /* prompt, and try again */ ! 393: goto YELL; ! 394: } ! 395: else ! 396: /* wait for response */ ! 397: { ! 398: clrtoeol(); ! 399: refresh(); ! 400: #ifdef BSD41 ! 401: sigset(SIGALRM, catchalarm); ! 402: #else ! 403: signal(SIGALRM, catchalarm); ! 404: #endif ! 405: /* set timeout */ ! 406: if (Timeout) ! 407: alarm(7); /* short */ ! 408: else ! 409: alarm(600); /* long */ ! 410: ! 411: ch = getchar(); ! 412: ! 413: alarm(0); /* turn off timeout */ ! 414: ! 415: if (ch < 0) ! 416: /* caught some signal */ ! 417: { ! 418: ++loop; ! 419: continue; ! 420: } ! 421: else if (ch == CH_REDRAW) ! 422: /* redraw screen */ ! 423: { ! 424: clearok(stdscr, TRUE); /* force clear screen */ ! 425: ++loop; /* don't count this input */ ! 426: continue; ! 427: } ! 428: else if (Echo) ! 429: { ! 430: addch(ch); /* echo character */ ! 431: refresh(); ! 432: } ! 433: ! 434: if (islower(ch)) ! 435: /* convert to upper case */ ! 436: ch = toupper(ch); ! 437: ! 438: if (def || strchr(choices, ch) != NULL) ! 439: /* valid choice */ ! 440: return(ch); ! 441: else if (!def && loop > 1) ! 442: /* bad choice; prompt, and try again */ ! 443: { ! 444: YELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices); ! 445: move(oldy, oldx); ! 446: clrtoeol(); ! 447: continue; ! 448: } ! 449: else ! 450: /* return default answer */ ! 451: break; ! 452: } ! 453: } ! 454: ! 455: return(*choices); ! 456: } ! 457: /**/ ! 458: /************************************************************************ ! 459: / ! 460: / FUNCTION NAME: catchalarm() ! 461: / ! 462: / FUNCTION: catch timer when waiting for input ! 463: / ! 464: / AUTHOR: E. A. Estes, 12/4/85 ! 465: / ! 466: / ARGUMENTS: none ! 467: / ! 468: / RETURN VALUE: none ! 469: / ! 470: / MODULES CALLED: longjmp() ! 471: / ! 472: / GLOBAL INPUTS: Timeoenv[] ! 473: / ! 474: / GLOBAL OUTPUTS: none ! 475: / ! 476: / DESCRIPTION: ! 477: / Come here when the alarm expires while waiting for input. ! 478: / Simply longjmp() into getanswer(). ! 479: / ! 480: /************************************************************************/ ! 481: ! 482: catchalarm() ! 483: { ! 484: longjmp(Timeoenv, 1); ! 485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.