Home | History | Annotate | Line # | Download | only in phantasia
io.c revision 1.1.1.1
      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 /**/
     95 /************************************************************************
     96 /
     97 / FUNCTION NAME: more()
     98 /
     99 / FUNCTION: pause and prompt player
    100 /
    101 / AUTHOR: E. A. Estes, 12/4/85
    102 /
    103 / ARGUMENTS:
    104 /	int where - line on screen on which to pause
    105 /
    106 / RETURN VALUE: none
    107 /
    108 / MODULES CALLED: wmove(), waddstr(), getanswer()
    109 /
    110 / GLOBAL INPUTS: *stdscr
    111 /
    112 / GLOBAL OUTPUTS: none
    113 /
    114 / DESCRIPTION:
    115 /	Print a message, and wait for a space character.
    116 /
    117 /************************************************************************/
    118 
    119 more(where)
    120 int	where;
    121 {
    122     mvaddstr(where, 0, "-- more --");
    123     getanswer(" ", FALSE);
    124 }
    125 /**/
    127 /************************************************************************
    128 /
    129 / FUNCTION NAME: infloat()
    130 /
    131 / FUNCTION: input a floating point number from operator
    132 /
    133 / AUTHOR: E. A. Estes, 12/4/85
    134 /
    135 / ARGUMENTS: none
    136 /
    137 / RETURN VALUE: floating point number from operator
    138 /
    139 / MODULES CALLED: sscanf(), getstring()
    140 /
    141 / GLOBAL INPUTS: Databuf[]
    142 /
    143 / GLOBAL OUTPUTS: none
    144 /
    145 / DESCRIPTION:
    146 /	Read a string from player, and scan for a floating point
    147 /	number.
    148 /	If no valid number is found, return 0.0.
    149 /
    150 /************************************************************************/
    151 
    152 double
    153 infloat()
    154 {
    155 double	result;		/* return value */
    156 
    157     getstring(Databuf, SZ_DATABUF);
    158     if (sscanf(Databuf, "%lf", &result) < 1)
    159 	/* no valid number entered */
    160 	result = 0.0;
    161 
    162     return(result);
    163 }
    164 /**/
    166 /************************************************************************
    167 /
    168 / FUNCTION NAME: inputoption()
    169 /
    170 / FUNCTION: input an option value from player
    171 /
    172 / AUTHOR: E. A. Estes, 12/4/85
    173 /
    174 / ARGUMENTS: none
    175 /
    176 / RETURN VALUE: none
    177 /
    178 / MODULES CALLED: floor(), drandom(), getanswer()
    179 /
    180 / GLOBAL INPUTS: Player
    181 /
    182 / GLOBAL OUTPUTS: Player
    183 /
    184 / DESCRIPTION:
    185 /	Age increases with every move.
    186 /	Refresh screen, and get a single character option from player.
    187 /	Return a random value if player's ring has gone bad.
    188 /
    189 /************************************************************************/
    190 
    191 inputoption()
    192 {
    193     ++Player.p_age;		/* increase age */
    194 
    195     if (Player.p_ring.ring_type != R_SPOILED)
    196 	/* ring ok */
    197 	return(getanswer("T ", TRUE));
    198     else
    199 	/* bad ring */
    200 	{
    201 	getanswer(" ", TRUE);
    202 	return((int) ROLL(0.0, 5.0) + '0');
    203 	}
    204 }
    205 /**/
    207 /************************************************************************
    208 /
    209 / FUNCTION NAME: interrupt()
    210 /
    211 / FUNCTION: handle interrupt from operator
    212 /
    213 / AUTHOR: E. A. Estes, 12/4/85
    214 /
    215 / ARGUMENTS: none
    216 /
    217 / RETURN VALUE: none
    218 /
    219 / MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
    220 /	getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
    221 /	crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
    222 /	getanswer()
    223 /
    224 / GLOBAL INPUTS: Player, *stdscr
    225 /
    226 / GLOBAL OUTPUTS: none
    227 /
    228 / DESCRIPTION:
    229 /	Allow player to quit upon hitting the interrupt key.
    230 /	If the player wants to quit while in battle, he/she automatically
    231 /	dies.
    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 
    243 #ifdef SYS3
    244     signal(SIGINT, SIG_IGN);
    245 #endif
    246 #ifdef SYS5
    247     signal(SIGINT, SIG_IGN);
    248 #endif
    249 
    250     savealarm = alarm(0);		/* turn off any alarms */
    251 
    252     getyx(stdscr, y, x);		/* save cursor location */
    253 
    254     for (loop = 0; loop < 80; ++loop)	/* save line on screen */
    255 	{
    256 	move(4, loop);
    257 	line[loop] = inch();
    258 	}
    259     line[80] = '\0';			/* nul terminate */
    260 
    261     if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
    262 	/* in midst of fighting */
    263 	{
    264 	mvaddstr(4, 0, "Quitting now will automatically kill your character.  Still want to ? ");
    265 	ch = getanswer("NY", FALSE);
    266 	if (ch == 'Y')
    267 	    death("Bailing out");
    268 	    /*NOTREACHED*/
    269 	}
    270     else
    271 	{
    272 	mvaddstr(4, 0, "Do you really want to quit ? ");
    273 	ch = getanswer("NY", FALSE);
    274 	if (ch == 'Y')
    275 	    leavegame();
    276 	    /*NOTREACHED*/
    277 	}
    278 
    279     mvaddstr(4, 0, line); 		/* restore data on screen */
    280     move(y, x);				/* restore cursor */
    281     refresh();
    282 
    283 #ifdef SYS3
    284     signal(SIGINT, interrupt);
    285 #endif
    286 #ifdef SYS5
    287     signal(SIGINT, interrupt);
    288 #endif
    289 
    290     alarm(savealarm);			/* restore alarm */
    291 }
    292 /**/
    294 /************************************************************************
    295 /
    296 / FUNCTION NAME: getanswer()
    297 /
    298 / FUNCTION: get an answer from operator
    299 /
    300 / AUTHOR: E. A. Estes, 12/4/85
    301 /
    302 / ARGUMENTS:
    303 /	char *choices - string of (upper case) valid choices
    304 /	bool def - set if default answer
    305 /
    306 / RETURN VALUE: none
    307 /
    308 / MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
    309 /	_filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
    310 /
    311 / GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
    312 /	Timeoenv[]
    313 /
    314 / GLOBAL OUTPUTS: _iob[]
    315 /
    316 / DESCRIPTION:
    317 /	Get a single character answer from operator.
    318 /	Timeout waiting for response.  If we timeout, or the
    319 /	answer in not in the list of valid choices, print choices,
    320 /	and wait again, otherwise return the first character in ths
    321 /	list of choices.
    322 /	Give up after 3 tries.
    323 /
    324 /************************************************************************/
    325 
    326 getanswer(choices, def)
    327 char	*choices;
    328 bool	def;
    329 {
    330 int	ch;			/* input */
    331 int	loop;			/* counter */
    332 int	oldx, oldy;		/* original coordinates on screen */
    333 
    334     getyx(stdscr, oldy, oldx);
    335     alarm(0);				/* make sure alarm is off */
    336 
    337     for (loop = 3; loop; --loop)
    338 	/* try for 3 times */
    339 	{
    340 	if (setjmp(Timeoenv) != 0)
    341 	    /* timed out waiting for response */
    342 	    {
    343 	    if (def || loop <= 1)
    344 		/* return default answer */
    345 		break;
    346 	    else
    347 		/* prompt, and try again */
    348 		goto YELL;
    349 	    }
    350 	else
    351 	    /* wait for response */
    352 	    {
    353 	    clrtoeol();
    354 	    refresh();
    355 #ifdef BSD41
    356 	    sigset(SIGALRM, catchalarm);
    357 #else
    358 	    signal(SIGALRM, catchalarm);
    359 #endif
    360 	    /* set timeout */
    361 	    if (Timeout)
    362 		alarm(7);		/* short */
    363 	    else
    364 		alarm(600);		/* long */
    365 
    366 	    ch = getchar();
    367 
    368 	    alarm(0);			/* turn off timeout */
    369 
    370 	    if (ch < 0)
    371 		/* caught some signal */
    372 		{
    373 		++loop;
    374 		continue;
    375 		}
    376 	    else if (ch == CH_REDRAW)
    377 		/* redraw screen */
    378 		{
    379 		clearok(stdscr, TRUE);	/* force clear screen */
    380 		++loop;			/* don't count this input */
    381 		continue;
    382 		}
    383 	    else if (Echo)
    384 		{
    385 		addch(ch);		/* echo character */
    386 		refresh();
    387 		}
    388 
    389 	    if (islower(ch))
    390 		/* convert to upper case */
    391 		ch = toupper(ch);
    392 
    393 	    if (def || strchr(choices, ch) != NULL)
    394 		/* valid choice */
    395 		return(ch);
    396 	    else if (!def && loop > 1)
    397 		/* bad choice; prompt, and try again */
    398 		{
    399 YELL:		mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
    400 		move(oldy, oldx);
    401 		clrtoeol();
    402 		continue;
    403 		}
    404 	    else
    405 		/* return default answer */
    406 		break;
    407 	    }
    408 	}
    409 
    410     return(*choices);
    411 }
    412 /**/
    414 /************************************************************************
    415 /
    416 / FUNCTION NAME: catchalarm()
    417 /
    418 / FUNCTION: catch timer when waiting for input
    419 /
    420 / AUTHOR: E. A. Estes, 12/4/85
    421 /
    422 / ARGUMENTS: none
    423 /
    424 / RETURN VALUE: none
    425 /
    426 / MODULES CALLED: longjmp()
    427 /
    428 / GLOBAL INPUTS: Timeoenv[]
    429 /
    430 / GLOBAL OUTPUTS: none
    431 /
    432 / DESCRIPTION:
    433 /	Come here when the alarm expires while waiting for input.
    434 /	Simply longjmp() into getanswer().
    435 /
    436 /************************************************************************/
    437 
    438 void
    439 catchalarm()
    440 {
    441     longjmp(Timeoenv, 1);
    442 }
    443