/*************************************************************************
**   File:  operterm.c
**      contains miscelaneous functions related to terminal output and
**	keyboard input.
**
**   Functions:
**	do_help() - displays help screen, including current function key
**		values
**	do_menu() - process first level menu selection
**	do_fil_men() - process 2nd level menu selection in File Menu
**	do_set_baud() - process 2nd level menu selection in Baud Rate Menu
**	do_ph_men() - process 2nd level menu selection in Phone Menu
**	emits() - output ascii string to terminal
**	emit() - output ascii character to terminal
**	toasc() - translates rawkey input to ascii character or function key
**	filename() - reads operator input in response to a request for a
**		file name
**	test_kbd_abort() - tests for operator's pressing ESC to abort
**		file transfer
**
*************************************************************************/
#include "term.h"
extern int	capture,
		cap_open,
		fd,
		send;
extern FILE	*trans;
extern char	name[];
extern struct IOExtSer *Read_Request;
extern struct Window *mywindow;
extern char func_key[20][64];
extern struct IntuiMessage *NewMessage;    /* msg structure for GetMsg() */

/********************************************************
**  help function 
********************************************************/

do_help()
{
	int i, j, k;
	char line[256], ldat[128], rdat[128];
	
	emits("      Term Plus - Version 2.1 --- by Bob Rakosky\n");
	emits("\nYou are automatically in TERMINAL mode--Use MENU functions for control functions\n");
	emits("ESC Aborts Xmodem Xfer\n\n");
	emits("\t\tFUNCTION KEYS:\n");
	emits("unshifted:\t\t\t     SHIFTED:\n");
	for (i=0;i<10;i++) {
		for (j=0,k=0;func_key[i][j];j++) {
			if (func_key[i][j] < ' ') {
				ldat[k++] = '^';
				ldat[k++] = func_key[i][j] + '@';
			}
			else ldat[k++] = func_key[i][j];
		}
		ldat[k] = '\0';
		for (j=0,k=0;func_key[i+10][j];j++) {
			if (func_key[i+10][j] < ' ') {
				rdat[k++] = '^';
				rdat[k++] = func_key[i+10][j] + '@';
			}
			else rdat[k++] = func_key[i+10][j];
		}
		rdat[k] = '\0';
		sprintf(line,"f%-2d = %-30s;F%-2d = %-30s\n",
			i+1,ldat,
			i+1,rdat);
		emits(line);
	}
	return(0);
}


do_menu(men,itm,sub)
	int men, itm, sub;
{
	switch( men )
	{
		case MENUNULL:
			return(0);
		case 0:
			do_fil_men(itm);
				break;
		case 1:
			do_set_baud(itm);
			break;
		case 2:		/*  Phone Lib Menu Pick */
			do_ph_men(itm,sub);
			break;
		case 3:		/* Function Key Menu */
			set_fkey();
			break;
	} /* end of switch ( men ) */
	return(0);
}

do_fil_men(item)
	int item;
{
	switch( item )
	{
		case 0:
			capture = !capture;
			if ((capture)&&(!cap_open)) {
				open_cap();
			}
			fix_menu();
			break;
		case 1:
			clos_cap();
			capture = FALSE;
			fix_menu();
			break;
		case 2:
			do_send();
			break;
		case 3:
			if (cap_open) flush_cap();
			emits("\nXmodem Receive:");
			filename(name);
			if (XMODEM_Read_File(name))
			{
				emits("\n\nRecieved File\n");
				emit(8);
			}
			else
			{
				close(fd);
				emits("\n\nXmodem Receive Failed\n");
				emit(8);
			}
			break;
		case 4:
			if (cap_open) flush_cap();
			emits("\nXmodem Send:");
			filename(name);
			if (XMODEM_Send_File(name))
			{
				emits("\n\nSent File\n");
				emit(8);
			}
			else
			{
				close(fd);
				emits("\n\nXmodem Send Failed\n");
				emit(8);
			}
			break;
	}
	return(0);
}

do_set_baud(item)
	int item;
{
	AbortIO(Read_Request);
	switch( item )
	{
		case 0:
			Read_Request->io_Baud = 300;
			break;
		case 1:
			Read_Request->io_Baud = 1200;
			break;
		case 2:
			Read_Request->io_Baud = 2400;
			break;
		case 3:
			Read_Request->io_Baud = 4800;
			break;
		case 4:
			Read_Request->io_Baud = 9600;
			break;
	}
	Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
	DoIO(Read_Request);
	Read_Request->IOSer.io_Command = CMD_READ;
	BeginIO(Read_Request);

	return(0);
}

do_ph_men(itm,sub)
	int itm,sub;
{
	if (itm==0)
		do_phlib();
	else
		dial(sub);
	return(0);
}


/*************************************************
*  function to print a string
*************************************************/
emits(string)
char string[];
{
	int i;
	char c;

	i=0;
	while (string[i] != 0)
	{
		c=string[i];
		if (c == 10)
			emit('\x0d');	/*  add CR */
		emit(c);
		i += 1;
	}
}



/*************************************************
*  function to output ascii chars to window
*************************************************/
emit(c)
char c;
{
	static short x = 0;
	static short y = 17;
	static short curs_on = 0;
	short xmax,ymax,cx,cy;

	xmax = mywindow->Width;
	ymax = mywindow->Height;

	/*  if character is control-char (except tab, cr, backspace,
	        form-feed, or bell) just return */
	if (c < ' ') {
		switch (c) {
		case '\t':
		case '\n':
		case 13:
		case 8:
		case 12:
		case 7: 
			break;
		default: 
			return(0);
		}
	}

	/* cursor */
	if (x > (xmax-8))
	{
		cx = 7;
		cy = y + 8;
	}
	else
	{
		cx = x+8;
		cy = y;
	}

	if (cy > (ymax-2))
	{
		cx = 7;
		cy -= 8;
	}

	if (curs_on) {
		SetDrMd(mywindow->RPort,COMPLEMENT);
		SetAPen(mywindow->RPort,3);
		RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
		SetAPen(mywindow->RPort,1);
		SetDrMd(mywindow->RPort,JAM2);
	}

	if (x > (xmax-8))
	{
		x = 0;
		y += 8;
	}

	if (y > (ymax-2))
	{
		x = 0;
		y -= 8;
	}

	Move(mywindow->RPort,x,y);

	switch( c )
	{
	case '\t':
		x += 60;
		break;
	case '\n':
		x = 0;
		y += 8;
		break;
	case 13:  /* newline */
		x = 0;
		curs_on = 0;
		return(0); 
	case 8:   /* backspace */
		x -= 8;
		if (x < 0)
			x = 0;
		break;
	case 12:     /* page */
		x = 0;
		y = 17;
		SetAPen(mywindow->RPort,0);
		RectFill(mywindow->RPort,0,10,xmax,ymax-7);
		SetAPen(mywindow->RPort,1);
		break;
	case 7:     /* bell */
		ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
		ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
		break;
	default:
		Text(mywindow->RPort,&c,1);
		x += 8;
	} /* end of switch */
	/* cursor */
	if (x > (xmax-8))
	{
		cx = 7;
		cy = y + 8;
	}
	else
	{
		cx = x+8;
		cy = y;
	}

	if (cy > (ymax-2))
	{
		cx = 7;
		cy -= 8;
		ScrollRaster(mywindow->RPort,0,8,0,10,xmax,ymax-2);
	}

	SetAPen(mywindow->RPort,3);
	RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
	SetAPen(mywindow->RPort,1);
	curs_on = 1;
}

/*************************************************
*  function to take raw key data and convert it 
*  into ascii chars
**************************************************/
toasc(code,qual)
USHORT code,qual;
{
	UBYTE c;
	int ix;
	
	static char v_key[150] = {
		'`','~',		/*  00  */
		'1','!',		/*  01  */
		'2','@',		/*  02  */
		'3','#',		/*  03  */
		'4','$',		/*  04  */
		'5','%',		/*  05  */
		'6','^',		/*  06  */
		'7','&',		/*  07  */
		'8','*',		/*  08  */
		'9','(',		/*  09  */
		'0',')',		/*  0a  */
		'-','_',		/*  0b  */
		'=','+',		/*  0c  */
		'\\','|',		/*  0d  */
		0,0,			/*  0e  */
		'0','0',		/*  0f  */
		'q','Q',		/*  10  */
		'w','W',		/*  11  */
		'e','E',		/*  12  */
		'r','R',		/*  13  */
		't','T',		/*  14  */
		'y','Y',		/*  15  */
		'u','U',		/*  16  */
		'i','I',		/*  17  */
		'o','O',		/*  18  */
		'p','P',		/*  19  */
		'[','{',		/*  1a  */
		']','}',		/*  1b  */
		0,0,			/*  1c  */
		'1','1',		/*  1d  */
		'2','2',		/*  1e  */
		'3','3',		/*  1f  */
		'a','A',		/*  20  */
		's','S',		/*  21  */
		'd','D',		/*  22  */
		'f','F',		/*  23  */
		'g','G',		/*  24  */
		'h','H',		/*  25  */
		'j','J',		/*  26  */
		'k','K',		/*  27  */
		'l','L',		/*  28  */
		';',':',		/*  29  */
		'\'','\"',		/*  2a  */
		0,0,			/*  2b  */
		0,0,			/*  2c  */
		'4','4',		/*  2d  */
		'5','5',		/*  2e  */
		'6','6',		/*  2f  */
		0,0,			/*  30  */
		'z','Z',		/*  31  */
		'x','X',		/*  32  */
		'c','C',		/*  33  */
		'v','V',		/*  34  */
		'b','B',		/*  35  */
		'n','N',		/*  36  */
		'm','M',		/*  37  */
		',','<',		/*  38  */
		'.','>',		/*  39  */
		'/','?',		/*  3a  */
		0,0,			/*  3b  */
		'.','.',		/*  3c  */
		'7','7',		/*  3d  */
		'8','8',		/*  3e  */
		'9','9',		/*  3f  */
		' ',' ',		/*  40  */
		'\010','\010',		/*  41  */
		'\011','\011',		/*  42  */
		'\r','\r',		/*  43  */
		'\r','\r',		/*  44  */
		'\033','\033',		/*  45  */
		'\x7f','\x7f',		/*  46  */
		0,0,			/*  47  */
		0,0,			/*  48  */
		0,0,			/*  49  */
		'-','-'   };		/*  4a  */

	if (code > '\x7f')
		return(0);
	
	if (code > '\x4a')
		return(-1);	/*  indicate special key (eg. function key) */
		
	ix = (code << 1);
	if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
		ix++;
	
	c = v_key[ix];
	if (!c)
		return(0);
		
	if (qual & IEQUALIFIER_CAPSLOCK)
		if ((c >= 'a') && (c <= 'z'))
			c -= ('a' - 'A');
	
	if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
		c |= '\x80';
	if (qual & IEQUALIFIER_CONTROL) 
		c &= 0x9f;
		
	return((int)c);
} /* end of routine */

/*************************************************
*  function to get file name
*************************************************/
filename(nam)
char nam[];
{
	int c;
	ULONG class;
	USHORT code, qual;
	int keepgoing,i;
	keepgoing = TRUE;
	i=0;
	while (keepgoing) {
		while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
		{
			class = NewMessage->Class;
			code = NewMessage->Code;
			qual = NewMessage->Qualifier;
			ReplyMsg( NewMessage );
			if (class==RAWKEY)
			{
				if ((c = toasc(code,qual)) > 0) {
					nam[i]=(char) c;
					if (nam[i] == 13)
					{
						nam[i]=0;
						keepgoing = FALSE;
					}
					else
					    {
						if (nam[i] == 8)
						{
							i -=2;
							if (i < -1)
								i = -1;
							else
							{
								emit(8);
								emit(32);
								emit(8);
							}
						}
						else
							emit(c);
					}
					i += 1;
				}
			}
		} /* end of new message loop */
	}   /* end of god knows what */
	emit(13);
} /* end of function */


test_kbd_abort()
{
	int resp = FALSE;
	
	while (NewMessage=
		(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
		if ((NewMessage->Class) == RAWKEY)
			if ((NewMessage->Code) == 69)
				resp = TRUE;
		ReplyMsg(NewMessage);
	}
	return(resp);
}
