* io.c - input/output routines for Phantasia
/************************************************************************
/ FUNCTION NAME: getstring()
/ FUNCTION: read a string from operator
/ AUTHOR: E. A. Estes, 12/4/85
/ char *cp - pointer to buffer area to fill
/ int mx - maximum number of characters to put in buffer
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
/ Read a string from the keyboard.
/ This routine is specially designed to:
/ - strip non-printing characters (unless Wizard)
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/ 'mx' is assumed to be at least 2.
/************************************************************************/
register char *inptr
; /* pointer into string for next string */
int x
, y
; /* original x, y coordinates on screen */
getyx(stdscr
, y
, x
); /* get coordinates on screen */
*inptr
= '\0'; /* clear string to start */
--mx
; /* reserve room in string for nul terminator */
/* get characters and process */
mvaddstr(y
, x
, cp
); /* print string on screen */
clrtoeol(); /* clear any data after string */
refresh(); /* update screen */
ch
= getchar(); /* get character */
case CH_ERASE
: /* back up one character */
case CH_KILL
: /* back up to original location */
case CH_NEWLINE
: /* terminate string */
case CH_REDRAW
: /* redraw screen */
default: /* put data in string */
/* printing char; put in string */
*inptr
= '\0'; /* terminate string */
while (ch
!= CH_NEWLINE
&& inptr
< cp
+ mx
);
/************************************************************************
/ FUNCTION: pause and prompt player
/ AUTHOR: E. A. Estes, 12/4/85
/ int where - line on screen on which to pause
/ MODULES CALLED: wmove(), waddstr(), getanswer()
/ Print a message, and wait for a space character.
/************************************************************************/
mvaddstr(where
, 0, "-- more --");
/************************************************************************
/ FUNCTION NAME: infloat()
/ FUNCTION: input a floating point number from operator
/ AUTHOR: E. A. Estes, 12/4/85
/ RETURN VALUE: floating point number from operator
/ MODULES CALLED: sscanf(), getstring()
/ GLOBAL INPUTS: Databuf[]
/ Read a string from player, and scan for a floating point
/ If no valid number is found, return 0.0.
/************************************************************************/
double result
; /* return value */
getstring(Databuf
, SZ_DATABUF
);
if (sscanf(Databuf
, "%lf", &result
) < 1)
/* no valid number entered */
/************************************************************************
/ FUNCTION NAME: inputoption()
/ FUNCTION: input an option value from player
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: floor(), drandom(), getanswer()
/ Age increases with every move.
/ Refresh screen, and get a single character option from player.
/ Return a random value if player's ring has gone bad.
/************************************************************************/
++Player
.p_age
; /* increase age */
if (Player
.p_ring
.ring_type
!= R_SPOILED
)
return(getanswer("T ", TRUE
));
return((int) ROLL(0.0, 5.0) + '0');
/************************************************************************
/ FUNCTION NAME: interrupt()
/ FUNCTION: handle interrupt from operator
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
/ getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
/ crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
/ GLOBAL INPUTS: Player, *stdscr
/ Allow player to quit upon hitting the interrupt key.
/ If the player wants to quit while in battle, he/she automatically
/ If SHELL is defined, spawn a shell if the if the question is
/ We are careful to save the state of the screen, and return it
/ to its original condition.
/************************************************************************/
char line
[81]; /* a place to store data already on screen */
register int loop
; /* counter */
int x
, y
; /* coordinates on screen */
unsigned savealarm
; /* to save alarm value */
register char *shell
; /* pointer to shell to spawn */
int childpid
; /* pid of spawned process */
savealarm
= alarm(0); /* turn off any alarms */
getyx(stdscr
, y
, x
); /* save cursor location */
for (loop
= 0; loop
< 80; ++loop
) /* save line on screen */
line
[80] = '\0'; /* nul terminate */
if (Player
.p_status
== S_INBATTLE
|| Player
.p_status
== S_MONSTER
)
/* in midst of fighting */
mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
ch
= getanswer("NY!", FALSE
);
ch
= getanswer("NY", FALSE
);
mvaddstr(4, 0, "Do you really want to quit [! = Shell] ? ");
ch
= getanswer("NY!", FALSE
);
mvaddstr(4, 0, "Do you really want to quit ? ");
ch
= getanswer("NY", FALSE
);
if ((shell
= getenv("SHELL")) == NULL
)
if ((childpid
= fork()) == 0)
cleanup(FALSE
); /* out of curses, close files */
setuid(getuid()); /* make sure we are running with real uid */
setgid(getgid()); /* make sure we are running with real gid */
execl(shell
, shell
, "-i", 0);
execl(SHELL
, SHELL
, "-i", 0); /* last resort */
while (wait((int *) NULL
) != childpid
); /* wait until done */
crmode(); /* restore keyboard */
clearok(stdscr
, TRUE
); /* force redraw of screen */
mvaddstr(4, 0, line
); /* restore data on screen */
move(y
, x
); /* restore cursor */
signal(SIGINT
, interrupt
);
signal(SIGINT
, interrupt
);
alarm(savealarm
); /* restore alarm */
/************************************************************************
/ FUNCTION NAME: getanswer()
/ FUNCTION: get an answer from operator
/ AUTHOR: E. A. Estes, 12/4/85
/ char *choices - string of (upper case) valid choices
/ bool def - set if default answer
/ MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
/ _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
/ GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
/ Get a single character answer from operator.
/ Timeout waiting for response. If we timeout, or the
/ answer in not in the list of valid choices, print choices,
/ and wait again, otherwise return the first character in ths
/************************************************************************/
int oldx
, oldy
; /* original coordinates on screen */
getyx(stdscr
, oldy
, oldx
);
alarm(0); /* make sure alarm is off */
for (loop
= 3; loop
; --loop
)
if (setjmp(Timeoenv
) != 0)
/* timed out waiting for response */
/* return default answer */
/* prompt, and try again */
sigset(SIGALRM
, catchalarm
);
signal(SIGALRM
, catchalarm
);
alarm(0); /* turn off timeout */
else if (ch
== CH_REDRAW
)
clearok(stdscr
, TRUE
); /* force clear screen */
++loop
; /* don't count this input */
addch(ch
); /* echo character */
/* convert to upper case */
if (def
|| strchr(choices
, ch
) != NULL
)
else if (!def
&& loop
> 1)
/* bad choice; prompt, and try again */
YELL
: mvprintw(oldy
+ 1, 0, "Please choose one of : [%s]\n", choices
);
/* return default answer */
/************************************************************************
/ FUNCTION NAME: catchalarm()
/ FUNCTION: catch timer when waiting for input
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: longjmp()
/ GLOBAL INPUTS: Timeoenv[]
/ Come here when the alarm expires while waiting for input.
/ Simply longjmp() into getanswer().
/************************************************************************/