/*
 * TTY setup routines. These are the BSD-style routines.
 */

static struct sgttyb  _raw_tty,     _original_tty;
static struct ltchars _raw_ltchars, _original_ltchars;
static struct tchars  _raw_tchars,  _original_tchars;
static int            _raw_lmode,   _original_lmode;

/*
 * current raw state
 */
static short _inraw = 0;

/*
 *  Set up the tty driver
 *
 * Args: state -- which state to put it in. 1 means go into raw (cbreak),
 *                0 out of raw.
 *
 * Result: returns 0 if successful and -1 if not.
 */
int
Raw(state)
int state;
{
    /** state is either ON or OFF, as indicated by call **/
    /* Check return code only on first call. If it fails we're done for and
       if it goes OK the others will probably go OK too. */

    if(state == 0 && _inraw){
        /*----- restore state to original -----*/
	if(ioctl(STDIN_FD, TIOCSETP, &_original_tty) < 0)
          return(-1);

	(void)ioctl(STDIN_FD, TIOCSLTC, &_original_ltchars);
	(void)ioctl(STDIN_FD, TIOCSETC, &_original_tchars);
        (void)ioctl(STDIN_FD, TIOCLSET, &_original_lmode);
        _inraw = 0;
    }
    else if(state == 1 && ! _inraw){
        /*----- Go into raw mode (cbreak actually) ----*/
        if(ioctl(STDIN_FD, TIOCGETP, &_original_tty) < 0)
          return(-1);

	(void)ioctl(STDIN_FD, TIOCGETP, &_raw_tty);   
        (void)ioctl(STDIN_FD, TIOCGETC, &_original_tchars);
	(void)ioctl(STDIN_FD, TIOCGETC, &_raw_tchars);
	(void)ioctl(STDIN_FD, TIOCGLTC, &_original_ltchars);
	(void)ioctl(STDIN_FD, TIOCGLTC, &_raw_ltchars);
        (void)ioctl(STDIN_FD, TIOCLGET, &_original_lmode);
        (void)ioctl(STDIN_FD, TIOCLGET, &_raw_lmode);

	_raw_tty.sg_flags &= ~(ECHO);	/* echo off */
	_raw_tty.sg_flags |= CBREAK;	/* raw on    */
        _raw_tty.sg_flags &= ~CRMOD;	/* Turn off CR -> LF mapping */

	_raw_tchars.t_intrc = -1;	/* Turn off ^C and ^D */
	_raw_tchars.t_eofc  = -1;

	_raw_ltchars.t_lnextc = -1;	/* Turn off ^V so we can use it */
	_raw_ltchars.t_dsuspc = -1;	/* Turn off ^Y so we can use it */
	_raw_ltchars.t_suspc  = -1;	/* Turn off ^Z; we just read 'em */
	_raw_ltchars.t_werasc = -1;	/* Turn off ^w word erase */
	_raw_ltchars.t_rprntc = -1;	/* Turn off ^R reprint line */
        _raw_ltchars.t_flushc = -1;	/* Turn off ^O output flush */
            
	(void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
	(void)ioctl(STDIN_FD, TIOCSLTC, &_raw_ltchars);
        (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
        (void)ioctl(STDIN_FD, TIOCLSET, &_raw_lmode);
	_inraw = 1;
    }

    return(0);
}


/*
 *  Set up the tty driver to use XON/XOFF flow control
 *
 * Args: state -- True to make sure XON/XOFF turned on, FALSE off.
 *
 * Result: none.
 */
void
xonxoff_proc(state)
int state;
{
    if(_inraw){
	if(state){
	    if(_raw_tchars.t_startc == -1 || _raw_tchars.t_stopc == -1){
		_raw_tchars.t_startc = 'Q' - '@'; /* Turn ON ^S/^Q */
		_raw_tchars.t_stopc  = 'S' - '@';
		(void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
	    }
	}
	else{
	    if(!(_raw_tchars.t_startc == -1 && _raw_tchars.t_stopc == -1)){
		_raw_tchars.t_startc = -1;	/* Turn off ^S/^Q */
		_raw_tchars.t_stopc  = -1;
		(void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
	    }
	}
    }
}


/*
 *  Set up the tty driver to do LF->CR translation
 *
 * Args: state -- True to turn on translation, false to write raw LF's
 *
 * Result: none.
 */
void
crlf_proc(state)
int state;
{
    if(_inraw){
	if(state){				/* turn ON NL->CR on output */
	    if(!(_raw_tty.sg_flags & CRMOD)){
		_raw_tty.sg_flags |= CRMOD;
		(void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
	    }
	}
	else{					/* turn OFF NL-CR on output */
	    if(_raw_tty.sg_flags & CRMOD){
		_raw_tty.sg_flags &= ~CRMOD;
		(void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
	    }
	}
    }
}


/*
 *  Set up the tty driver to hanle interrupt char
 *
 * Args: state -- True to turn on interrupt char, false to not
 *
 * Result: tty driver that'll send us SIGINT or not
 */
void
intr_proc(state)
int state;
{
    if(_inraw){
	if(state){
	    _raw_tchars.t_intrc = ctrl('C');
	    (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
	}
	else{
	    _raw_tchars.t_intrc = -1;
	    (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
	}
    }
}


/*
 * Discard any pending input characters
 *
 * Args:  none
 *
 * Result: pending input buffer flushed
 */
void
flush_input()
{
#ifdef	TIOCFLUSH
#ifdef	FREAD
    int i = FREAD;
#else
    int i = 1;
#endif
    ioctl(STDIN_FD, TIOCFLUSH, &i);
#endif	/* TIOCFLUSH */
}


/*
 * Turn off hi bit stripping
 */
void
bit_strip_off()
{
    _raw_lmode |= LPASS8;
#ifdef	NXT
    _raw_lmode |= LPASS8OUT;
#endif
    (void)ioctl(STDIN_FD, TIOCLSET, &_raw_lmode);
}


/*
 * Turn off quit character (^\) if possible
 */
void
quit_char_off()
{
    _raw_tchars.t_quitc = -1;
    (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
}


/*
 * Returns TRUE if tty is < 4800, 0 otherwise.
 */
int
ttisslow()
{
    return((int)_raw_tty.sg_ispeed < B4800);
}


