/******************************************************************************
 * This file is part of a software distribution, which is furnished under the *
 * terms of a license.  Use of this software  by any means is subject to this *
 * license  and  signifies  the  acceptance of  the  licensing  terms  stated *
 * therein. Please see  the file LICENSE in the  top-level directory  of this *
 * software  distribution  for detailed copyright  disclaimers  and licensing *
 * terms.                                                                     *
 ******************************************************************************
 * Copryight (c) by Andreas S. Wetzel - All rights reserved.                  *
 ******************************************************************************/

/* $Id: vd_input.c,v 1.3 2001/03/19 23:17:29 mickey Exp $ */

#include <vchat.h>
#include <proto_vchatd.h>

#include <ctype.h>

/*** Globals ***/

ED	main_ed;
ED	*ed = &main_ed;

/*** Externals ***/

extern int in_chat_window;

extern VP vp;
extern VTCAP vtcap;

/*
 * int input_line(char *prompt, size_t maxlen, u_short flags);
 *
 * Read input from the users terminal up to maxlen characters (or the
 * maximum possible length if maxlen is given as 0) and return the number
 * of bytes actually read into the global ED buffer pointed to by the global
 * ed variable. Flags should be the bitwise OR of any of the following flags:
 *
 * ED_RST_CTX	- Reset input context upon startup
 * ED_NO_ECHO	- Suppress terminal echo while reading input
 *
 */

int input_line(char *prompt, size_t maxlen, u_short flags)
{
	static char lterm = 0;
	u_char c;
	u_char cx;

	/*** Lock all interrupts during init ***/

	vlock(LOCK, (V_IO | V_TIMER));

	/*** Disable videosnake ***/

	snake_disable();

	/**** Buffer init ****/

	if(flags & ED_RST_CTX)
	{
		/*
		 * Reset input context upon startup
		 */

		BZERO(&ed->buffer, EDBUFSIZE+1);
		ed->endpos = ed->curpos = ed->margin = (char *) &ed->buffer;
		ed->prompt = NULL;
	}

	if(prompt)
		ed->prompt = prompt;

	ed->offset = (ed->prompt != NULL) ? real_len(ed->prompt) : 0;
	ed->maxlen = (maxlen > 0 && maxlen < EDBUFSIZE) ? maxlen : EDBUFSIZE;
	ed->flags = flags;

	/***** window init *****/

	line_update();

	/*** init completed - unlock interrupts ***/

	vlock(UNLOCK, (V_IO | V_TIMER));

	/*** Wait for user input ***/

	for(;;)
	{
		/* Get character */

		switch(read(0, &c, 1))
		{
			case 1:		break;
			case 0:		log(VLOG_ERR, "TELNET connection closed by remote host");
					snd_serv(CMD_SIGNOFF, NULL, 0);
					vquit(NULL);
			case -1:	log(VLOG_ERR, "read error on TELNET connection (%s)",
						strerror(errno));
					snd_serv(CMD_SIGNOFF, NULL, 0);
					vquit(NULL);
			default:	log(VLOG_ERR, "Oooops!!!");
					snd_serv(CMD_SIGNOFF, NULL, 0);
					vquit("Oooops!!!");
		}

		/* End of line? */

		if((c == CR && lterm != LF)
		|| (c == LF && lterm != CR))
		{
			lterm = c;
			break;
		}
		else if(c == CR || c == LF)
		{
			continue;
		}

		/* Filter for incoming telnet commands */

		if(!(cx = tel_filter(c)))
			continue;

		vlock(LOCK, (V_IO | V_TIMER));

		snake_enable();

		if(is_key_sequence(vtcap.key_cursleft, cx))
		{
			curs_left();
		}
		else if(is_key_sequence(vtcap.key_cursright, cx))
		{
			curs_right();
		}
		else if(is_key_sequence(vtcap.key_cursup, cx))
		{
			if((ed->flags & ED_HISTORY) != 0
			&& vp.history_current != vp.history_start)
			{
				snake_disable();
				vlock(UNLOCK, (V_IO | V_TIMER));
				return(-2);
			}
			else
			{
				nop();
			}
		}
		else if(is_key_sequence(vtcap.key_cursdown, cx))
		{
			if((ed->flags & ED_HISTORY) != 0
			&& vp.history_current != vp.history_next)
			{
				snake_disable();
				vlock(UNLOCK, (V_IO | V_TIMER));
				return(-4);
			}
			else
			{
				nop();
			}
		}
		else if(is_key_sequence(vtcap.key_insert, cx))
		{
			ungetc(' ', stdin);
		}
		else if(is_key_sequence(vtcap.key_delete, cx))
		{
			delete();
		}
		else if(iscntrl(cx))
		{
			switch(cx)
			{
				case DEL:
				case BS:	backspace();
						break;

				case CTL_A:	jump_start();
						break;

				case CTL_E:	jump_end();
						break;

				case CTL_D:	delete();
						break;

				case CTL_K:	erase_eol();
						break;

				case CTL_U:	erase_line();
						break;

				case CTL_F:	word_forward();
						break;

				case CTL_B:	word_reverse();
						break;

				case CTL_L:	line_update();
						break;

				case HT:	tabcomplete();
						break;

				default:	break;
			}
		}
		else
		{
			if(ed->curpos != ed->endpos)
			{
				/*
				 * Insert mode
				 */

				insert_char(cx);
			}
			else
			{
				/*
				 * Append mode
				 */

				append_char(cx);
			}
		}

		vlock(UNLOCK, (V_IO | V_TIMER));
	}

	if(ED_USED)
	{
		vlock(LOCK, (V_IO | V_TIMER));

		mv(1, vtcap.rows);

		in_chat_window = 0;

		if(vtcap.clear2eol)
			tputs(vtcap.clear2eol, 1, (void *)outc);
		else if(vtcap.clear2eod)
			tputs(vtcap.clear2eod, 1, (void *)outc);

		vlock(UNLOCK, (V_IO | V_TIMER));
	}

	return(ED_USED);
}


syntax highlighted by Code2HTML, v. 0.9.1