/* TTY input driver */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "session.h"
#include "tty.h"
#include "socket.h"

#define	OFF	0
#define	ON	1


#define	LINESIZE	256

#define	CTLU	21
#define CTLR	18
#define	CTLZ	26

/* Accept characters from the incoming tty buffer and process them
 * (if in cooked mode) or just pass them directly (if in raw mode).
 *
 * Note that echoing is direct to the terminal, not through the session
 * output buffering system.
 */
 /*Control-R added by df for retype of lines - useful in Telnet */
 
struct mbuf *
ttydriv(sp,c)
struct session *sp;
char c;
{
	struct mbuf *bp;
	char *cp,*rp;

	switch(sp->ttystate.edit){
	case OFF:
		if((bp = alloc_mbuf(1)) == NULLBUF)
			return NULLBUF;
		*bp->data = c;
		bp->cnt = 1;
		if(sp->ttystate.echo)
			usputc(sp->output,c);
		return bp;
	case ON:
		if(sp->ttystate.line == NULLBUF
		 && (sp->ttystate.line = alloc_mbuf(LINESIZE)) == NULLBUF)
			return NULLBUF;

		bp = sp->ttystate.line;
		cp = bp->data + bp->cnt;
		/* Perform cooked-mode line editing */
		switch(c & 0x7f){
		case '\r':	/* CR and LF both terminate the line */
		case '\n':
			if(sp->ttystate.crnl)
				*cp = '\n';
			else
				*cp = c;
			if(sp->ttystate.echo)
				usputc(sp->output,'\n');
			bp->cnt += 1;
			sp->ttystate.line = NULLBUF;
			return bp;
		case '\b':		/* Backsp->ttystateace */
			if(bp->cnt != 0){
				bp->cnt--;
				if(sp->ttystate.echo)
					usputs(sp->output,"\b \b");
			}
			break;
		case CTLR:	/* print line buffer */
			if(sp->ttystate.echo){
				usputs(sp->output,"^R\n") ;
				rp = bp->data;
				while (rp < cp)
					usputc(sp->output,*rp++) ;
			}
			break ;
		case CTLU:	/* Line kill */
			while(bp->cnt != 0){
				bp->cnt--;
				if(sp->ttystate.echo){
					usputs(sp->output,"\b \b");
				}
			}
			break;
		default:	/* Ordinary character */
			*cp = c;
			bp->cnt++;

			/* ^Z apparently hangs the terminal emulators under
			 * DoubleDos and Desqview. I REALLY HATE having to patch
			 * around other people's bugs like this!!!
			 */
			if(sp->ttystate.echo &&
#ifndef	AMIGA
			 c != CTLZ &&
#endif
			 bp->cnt < LINESIZE-1){
				usputc(sp->output,c);

			} else if(bp->cnt >= LINESIZE-1){
				usputc(sp->output,'\007');	/* Beep */
				bp->cnt--;
			}
			break;
		}
		break;
	}
	return NULLBUF;
}
