/******************************************************************************

	ZChIn()

	This function inputs a single character from the terminal.

	1.  the character is not echoed on the terminal
	2.  ^C calls an interrupt routine.  Note that this must be
	    implemented so that a ^C will cancel a current output via
	    ZDspBf.  The ^C must be a true interrupt.
	3.  type-ahead is always nice
	4.  The character must be returned immediately:  no fooling
	    around waiting for a carriage-return before returning.
	5.  If the no wait bit in the ET flag is set,  don't wait.
	6.  When the user hits the RETURN key,  TECO is supposed to see
	    a carriage return and then a line feed.  The function must
	    deal with this by returning a carriage return to the caller
	    and then "remembering" to send a line feed on the next call.

*****************************************************************************/

#include "ZPort.h"		/* define portability identifiers */
#include "DefTeco.h"		/* define general identifiers */

EXTERN	BOOLEAN	GotCtC;		/* YES if a control-C was hit */


#ifdef UNKNOWN
char ZChIn()			/* input a character from terminal */
{
	puts("Terminating in function ZChIn.\n");
	exit(1);
}
#endif



#ifdef vax11c
#include "DefChars.h"	/* define identifiers for characters */
#include iodef		/* define i/o code identifiers */
#include rab		/* define RMS record access block structures */
#include rmsdef		/* define RMS return status identifiers */
#include ssdef		/* define system service status return identifiers */

VOID	lib$stop();		/* terminate image with stack dump */
int	sys$get();		/* RMS GET service */
int	sys$qiow();		/* VAX/VMS "queue i/o" system service */

EXTERN	WORD	EtFlag;		/* ET mode control flag */
EXTERN	BOOLEAN	NoWait;		/* wait for input character? */
EXTERN	char	*TIBBeg;	/* terminal buffer beginning */
EXTERN	char	*TIBEnd;	/* terminal buffer end */
EXTERN	char	*TIBERc;	/* ptr to end of record in buffer */
EXTERN	char	*TIBPtr;	/* ptr to current character in record */
EXTERN	struct	RAB TIRab;	/* term input record access block */
EXTERN	short	TIChan;		/* terminal channel */


char ZChIn()			/* input a character from terminal */
{
	auto	int	Charac;
	static	int	io_function =	IO$_READVBLK|
					IO$M_NOFILTR|
					IO$M_NOECHO;
	static	BOOLEAN	LastCR = NO;
	auto	int	status;
	struct	io_status_block tt_iosb;


	if (TIChan)				/* if it's a terminal */
		{
		if (LastCR)			/* if last char was a <CR> */
			{
			LastCR = NO;
			return(LINEFD);
			}
		if (NoWait)
			io_function |= IO$M_TIMED;
		else
			io_function &= ~IO$M_TIMED;
		Charac = 0;
		status = sys$qiow(
				TERM_IN_EFN,	/* event flag number */
				TIChan,		/* channel */
				io_function,	/* I/O function */
				&tt_iosb,	/* I/O status block */
				0,		/* ast routine address */
				0,		/* ast parameter */
				&Charac,	/* input buffer */
				1,		/* input buffer size */
				0,		/* p3 */
				0,		/* p4 */
				0,		/* p5 */
				0);		/* p6 */

		if (status != SS$_NORMAL)
			lib$stop(status);

		switch (tt_iosb.io_status) {
			case SS$_NORMAL:
			case SS$_ABORT:
			case SS$_CONTROLC:
				break;
			case SS$_TIMEOUT:
				return('\0');
			default:
				lib$stop(tt_iosb.io_status);
			}
		if (Charac == CRETRN)
			LastCR = YES;
		}
	else						/* else not terminal */
		{
		if (TIBPtr = TIBERc)			/* if record used up */
			{
			status = sys$get(&TIRab);	/* get next record */
			if (status != RMS$_NORMAL)
				lib$stop(status, TIRab.rab$l_stv);
			TIBERc = &TIBBeg[TIRab.rab$w_rsz];
			*TIBERc++ = CRETRN;
			*TIBERc++ = LINEFD;
			TIBPtr = TIBBeg;
			}
		Charac = *TIBPtr++;
		}
	return(Charac);
}
#endif



#ifdef XENIX

EXTERN	int	tty_fd;

char ZChIn()			/* input a character from terminal */
{
	char	Charac;

	if (read(tty_fd, &Charac, 1) != 1)
		if (!GotCtC)
			{
			puts("read failed in function ZChIn");
			ZAbort();
			}
	return(Charac);
}
#endif
