/********************************************************************
 *  vt100 terminal emulator with xmodem transfer capability
 *
 *	v2.8 880117 ACS - See the README file
 *	v2.7 870825 ACS - Provide handling of the msgs from the
 *			  info/status window.
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860901 ACS - Added Parity and Word Length and support code
 *	     860823 DBW - Integrated and rewrote lots of code
 *	v2.0 860809 DBW - Major rewrite
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 *  use <esc> to abort xmodem or kermit transfers
 *
 *  written by Michael Mounier
 *  new version by Dave Wecker
 *******************************************************************/

/*  all includes defines and globals */
#include "vt100.h"

APTR OrigWindowPtr;	/* Used by init.c when opening a new screen */

/**************************************************************/
/* here are all the global definitions that appear in vt100.h */
/**************************************************************/

char    bufr[BufSize];
int     fd, timeout = FALSE, ttime;
int	multi = FALSE, server;
long    bytes_xferred;
char	MyDir[60];
BPTR	StartLock = 0;
struct	IntuitionBase *IntuitionBase;
struct	GfxBase *GfxBase;

extern char myfontname[];		/* In script.c */

struct	TextAttr myattr = {
    (STRPTR)(&(myfontname[0])),
    8,
    0,
    0};
struct	TextFont *myfont = NULL;
struct NewScreen NewScreen = {
   0,0,640,200,1,		/* left, top, width, height, depth */
   0,1,HIRES,			/* DetailPen, BlockPen, ViewModes */
   CUSTOMSCREEN,&myattr,	/* Type, Font */
   (UBYTE *)"VT100",		/* Title */
   NULL,NULL };			/* Gadgets, Bitmap */
struct NewWindow NewWindow = {
   0,0,640,200,			/* left, top, width, height */
   0,1,				/* detailpen, blockpen */
   MENUPICK|CLOSEWINDOW|RAWKEY|ACTIVEWINDOW|INACTIVEWINDOW,
   SMART_REFRESH|ACTIVATE|BORDERLESS|WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
   NULL,NULL,			/* FirstGadget, CheckMark */
   (UBYTE *)NULL,
   NULL,			/* set screen after open screen */
   NULL,			/* bitmap */
   640, 200, 640, 200,		/* minw, minh, maxw, maxh */
   CUSTOMSCREEN			/* Type */
   };
struct NewWindow NewReqWindow = {
   10, 15, ((54*8)+4+18), ((4*8)+11+2), /* left, top, width, height */
   0, 1,			/* detailpen, blockpen */
	/* IDCMP Flags... */
   CLOSEWINDOW | ACTIVEWINDOW | REQCLEAR | REQSET | NEWSIZE,
	/* Flags... */
   SMART_REFRESH | NOCAREREFRESH | ACTIVATE | WINDOWSIZING | SIZEBRIGHT |
   WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG,

   NULL,			/* First gadget */
   NULL,			/* CheckMark */
   (UBYTE *)"VT100 Info & Xfer Status",	/* Title */
   NULL,			/* set screen after open screen */
   NULL,			/* bitmap */
   ((5*8)+4+18), ((1*8)+11+2), 640, 200,	/* minw, minh, maxw, maxh */
   CUSTOMSCREEN			/* Type */
   };
struct IntuiText MyTitle = {
    0,1,JAM2,26,0,		/* front pen, back pen, mode, left, top */
    &myattr,			/* font */
    (UBYTE *)VERSION,		/* title */
    NULL};			/* next text */

struct Screen *myscreen = NULL;		/* ptr to applications screen */
struct Window *mywindow = NULL;		/* ptr to applications window */
struct Window *reqwindow = NULL;	/* ptr to requester's window */
struct ViewPort *myviewport;
struct RastPort *myrastport;
struct IntuiMessage *NewMessage;	/* msg structure for GetMsg() */
struct Preferences  *Prefs;		/* preferences from GetPrefs() */

/**** String requester support ******/

char	InpBuf[80],UndoBuf[80],Prompt[80];
struct IntuiText donetxt = {
    1,0,JAM2,0,0,	/* front pen, back pen, mode, left, top */
    &myattr,		/* font */
    (UBYTE *)"DONE",	/* question to ask */
    NULL};		/* next text */
struct Gadget mydonegad = {
    &mystrgad,290,2,40,10,	/* next,left,top,width,height */
    GADGHCOMP|REQGADGET,	/* flags */
    RELVERIFY|ENDGADGET,	/* activation */
    BOOLGADGET,			/* gadget type */
    NULL,NULL,&donetxt,		/* gad render, sel render, gad text */
    0L,NULL,2,NULL};		/* mutual exclude, special, ID, user data */
struct	StringInfo mystrinfo = {
    (UBYTE *)InpBuf,
    (UBYTE *)UndoBuf,
    0,80,0,0,0,0,	/* initial, max, disp, undo, #chrs, dsp chrs */
    0,0,NULL,0L,NULL};	/* left,top,layer,longint,keymap */
struct Gadget mystrgad = {
    NULL,10,12,320,10,	/* next,left,top,width,height */
    GADGHCOMP|REQGADGET,/* flags */
    ENDGADGET,STRGADGET,/* activation, type */
    NULL,NULL,NULL,	/* gad render, sel render, gad text */
    0L,			/* mutual exclude */
    (APTR)&mystrinfo,	/* special info */
    1,NULL};		/* gadget ID, user data */
struct IntuiText mystrtxt = {
    0,1,JAM2,10,2,	/* front pen, back pen, mode, left, top */
    &myattr,		/* font */
    (UBYTE *)Prompt,	/* question to ask */
    NULL};		/* next text */
struct Requester myrequest = {
    NULL,5,10,340,22,	/* older requester, left, top, width, height */
    0,0,&mydonegad,	/* relleft reltop, gadgets */
    NULL,		/* border */
    &mystrtxt,		/* text */
    NULL,1,NULL,	/* flags, back fill pen, layer */
    {0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0},	/* pad1 */
    NULL,NULL,		/* image bit map, rquest window */
    {0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0} /* pad2 */
    };

int numreqs = 0;		/* number of outstanding requestors */
int reqwinup = 0;		/* Requester window is NOT displayed */
extern int reqmaxx, reqmaxy, reqmaxlen;	/* Defined in window.c */
extern void ReqNewSize();	/* New req window size -- window.c */
extern void KillReq();		/* Kill requester window in window.c */	

/***** menu structures *****/
struct MenuItem FileItem[FILEMAX];
struct IntuiText FileText[FILEMAX];
struct MenuItem ModeItem[MODEMAX];
struct IntuiText ModeText[MODEMAX];
struct MenuItem CommItem[COMMAX];
struct IntuiText CommText[COMMAX];
struct MenuItem RSItem[RSMAX];
struct IntuiText RSText[RSMAX];
struct MenuItem ParItem[PARMAX];
struct IntuiText ParText[PARMAX];
struct MenuItem XFItem[XFMAX];
struct IntuiText XFText[XFMAX];
struct MenuItem ScriptItem[SCRIPTMAX];
struct IntuiText ScriptText[SCRIPTMAX];
struct MenuItem UtilItem[UTILMAX];
struct IntuiText UtilText[UTILMAX];
struct Menu menu[MAXMENU];
struct IOExtSer *Read_Request;
char *rs_in;
struct IOExtSer *Write_Request;
char rs_out[2];
struct timerequest Timer;
struct MsgPort *Timer_Port = NULL;
struct timerequest Script_Timer;
struct MsgPort *Script_Timer_Port = NULL;
struct IOAudio Audio_Request;
struct MsgPort *Audio_Port = NULL;
UBYTE  *BeepWave;
UBYTE  Audio_AllocMap[4] = { 1, 8, 2, 4 };
int x,y,curmode;
int MINX	= 0;
int MAXX	= 632;
int MINY	= 14;
int MAXY	= 198;
int top		= 14;
int bot		= 198;
int savx	= 0;
int savy	= 14;
int savmode	= 0;
int nlmode	= 0;
int alt		= 0;
int savalt	= 0;
int a[2]	= { 0, 0 };
int sa[2]	= { 0, 0 };
int  inesc	= -1;
int  inctrl	= -1;
int  private	= 0;
int  badseq	= 0;
int  maxcol	= 79;

/*************************** defaults *******************************/
char	*p_font		= "topaz";	/* Default font. Name must be < 34 chars */
int	p_baud		= 1200;	/* baud rate */
int	p_screen	= 0;	/* 0 = WORKBENCH, 1 = CUSTOM */
int	p_wbcolors	= 1;	/* 0 = Custom, 1 = Workbench colors */
int	p_interlace	= 0;	/* 0 = no interlace,    1 = interlace */
int	p_depth		= 2;	/* number of bit planes (1 or 2) */
int	p_foreground	= 0x840;	/* default foreground RGB color */
int	p_background	= 0x000;	/* default background RGB color */
int	p_bold		= 0x000;	/* default BOLD       RGB color */
int	p_cursor	= 0x00d;	/* default Cursor	  RGB color */
int	p_lines		= 24;	/* 0 == use all available (MoreRows) */
int	p_mode		= 0;	/* 0 = image, 1 = CRLF (for kermit) */
int	p_unit		= 0;	/* unit of serial.device to open */
int	p_xproto	= 3;	/* 0=ASCII, 1=Xmodem, 2=XmodemCRC, 3 = Kermit */
int	p_buffer	= 512;	/* read buffer size (>= 512 bytes) */
int     p_parity	= 0;	/* 0=none,1=mark,2=space,3=even,4=odd */
long	p_break		= 750000;	/* break time (in micro seconds) */
int	p_volume	= 64;	/* beep volume (0 = DisplayBeep) */
int	p_wrap		= 1;	/* 0 = truncate, 1 = wrap long lines */
int	p_keyapp	= 0;	/* 0 = numeric, 1 = application keypad */
int	p_curapp	= 0;	/* 0 = cursor, 1 = application cursor */
int	p_echo		= 0;	/* 0 = full duplex, 1 = half duplex */
int	p_bs_del	= 0;	/* 0 = normal, 1 = swap bs and delete */
int	p_convert	= 0;	/* 1 = convert filenames to lower case */
int	p_kmaxpack	= 1000;	/* Max packet size for Kermit xfers */
/*	Must be <= 1000.  <= 94 is standard, > 94 requires a kermit capable
**	of long packet support. */
int	p_xbeep		= 1;	/* 1 = beep at end of xfer */
char	p_keyscript	= 0x7E;	/* function key script introducer = ~ */
char	*p_f[10]	= {	/* function key defaults */
    "\033OP","\033OQ","\033OR","\033OS",
    "f5","f6","f7","f8","f9","f10" };

char	*p_F[10]     = {	    /* shifted function key defaults */
    "F1","F2","F3","F4","F5",
    "F6","F7","F8","F9","F10"};

/* for script file */
int script_on;
int script_wait;
int doing_init = 0;

/******************************************************/
/*                   Main Program                     */
/*                                                    */
/*      This is the main body of the program.         */
/******************************************************/

char lookahead[80];
FILE *tranr = NULL;
FILE *trans = NULL;
int capture,send;
char name[80];
struct MsgPort *mySerPort;

main(argc,argv)
int	argc;
char	**argv;
    {
    ULONG class, waitmask;
    unsigned int code, qual;
    APTR iaddr;
    int KeepGoing,i,la,dola,actual, len;
    char c,*ptr;
    char ascstr[100];	/* Area for string returned by toasc() */

    ptr = InitDefaults(argc,argv);
    InitDevs();
    InitFileItems();
    InitCommItems();
    InitScriptItems();
    InitUtilItems();
    InitMenu();
    SetMenuStrip(mywindow,&menu[0]);
    PrintIText(mywindow->RPort,&MyTitle,0L,0L);

    MyDir[0]  =	    '\000';
    StartLock = ((struct Process *) FindTask(NULL))->pr_CurrentDir;
    CurrentDir(DupLock(StartLock));
    KeepGoing =	    TRUE;
    capture   =	    FALSE;
    send      =	    FALSE;
    maxcol    =	    MAXX / 8;
    la	      =	    0;
    x	      =	    MINX ;
    y	      =	    MINY;
    curmode   =	    FS_NORMAL;
    script_on =     FALSE;
    script_wait=    TRUE;
    SetAPen(mywindow->RPort,1L);
    cursorflip();
    cursorflip();
    emit(12);
    mySerPort = Read_Request->IOSer.io_Message.mn_ReplyPort;
    SendIO(Read_Request);

    /* see if we had a startup script */
    if (ptr != NULL) script_start(ptr);

    while( KeepGoing )
	    {
	    /* wait for window message or serial port message */
	    cursorflip();
	    if(reqwinup)
		waitmask = (1L << mySerPort->mp_SigBit) |
			   (1L << mywindow->UserPort->mp_SigBit) |
			   (1L << Script_Timer_Port->mp_SigBit) |
			   (1L << reqwindow->UserPort->mp_SigBit);
	    else
		waitmask = (1L << mySerPort->mp_SigBit) |
			   (1L << mywindow->UserPort->mp_SigBit) |
			   (1L << Script_Timer_Port->mp_SigBit);
	    if (script_wait)	/* if script ready dont wait here */
		Wait(waitmask);
	    cursorflip();

	    /* do ascii file send */
	    if (send)
		{
		if ((c=getc(trans)) != EOF) {
		    if (c == '\n') c = '\r';
		    sendchar(c);
		    }
		else {
		    fclose(trans);
		    InfoMsg1Line("File Sent");
		    send=FALSE;
		    }
		}

	    /* see if there are any characters from the host */
	    if (CheckIO(Read_Request)) {
		WaitIO(Read_Request);
		c = rs_in[0] & 0x7F;
		doremote(c);
		if (script_on) chk_script(c);
		if (capture && c != 10) {
		    if (c == 13) c = 10;
		    putc(c , tranr);
		    }
		Read_Request->IOSer.io_Command = SDCMD_QUERY;
		DoIO(Read_Request);
		Read_Request->IOSer.io_Command = CMD_READ;
		actual = (int)Read_Request->IOSer.io_Actual;
		if (actual > 0) {
		    if (inesc   <  0 &&
			inctrl  <  0 &&
			a[alt]  == 0 &&
			capture == FALSE) dola = 1;
		    else dola = 0;
		    Read_Request->IOSer.io_Length =
			Read_Request->IOSer.io_Actual;
		    DoIO(Read_Request);
		    Read_Request->IOSer.io_Length = 1;

		    for (i = 0; i < actual; i++) {
			c=rs_in[i] & 0x7f;
			if (script_on) chk_script(c);

			if (dola == 1) {
			    if (c >= ' ' && c <= '~' && la < 80)
				lookahead[la++] = c;
			    else {
				if (la > 0) {
				    emitbatch(la,lookahead);
				    la = 0;
				    }
				doremote(c);
				dola = 0;
				}
			    }
			else {
			    doremote(c);
			    if (inesc   <  0 &&
				inctrl  <  0 &&
				a[alt]  == 0 &&
				capture == FALSE) dola = 1;
			    if (capture && c != 10) {
				if (c == 13) c = 10;
				putc(c , tranr);
				}
			    }
			}

		    /* dump anything left in the lookahead buffer */
		    if (la > 0) {
			emitbatch(la,lookahead);
			la = 0;
			}
		    }
		SendIO(Read_Request);
 		}

	    while((NewMessage =
		    (struct IntuiMessage *)GetMsg(mywindow->UserPort))
			!= FALSE) {
		class = NewMessage->Class;
		code = NewMessage->Code;
		qual = NewMessage->Qualifier;
		if(class == RAWKEY)
		    iaddr = *((APTR *)NewMessage->IAddress);
		ReplyMsg( NewMessage );
		switch( class )
		    {
		    case CLOSEWINDOW:
		    KeepGoing = FALSE;
		    break;

		    case RAWKEY:
		    len = toasc(&(ascstr[0]), code,qual, 100, iaddr, 0);
		    if (p_echo) {
			ptr = &(ascstr[0]);
			for(i = 0; i < len; i++)
			    doremote(*(ptr++));
		    }
		    break;

		    case NEWSIZE:
		    emit(12);
		    break;

		    case MENUPICK:
		    handle_menupick(class,code);
		    break;

		    default:
		    PrintIText(mywindow->RPort,&MyTitle,0L,0L);
		    break;
		    }   /* end of switch (class) */
		}   /* end of while ( newmessage )*/

	    if (!script_wait ||
		 (CheckIO(&Script_Timer) &&
		    script_wait == WAIT_TIMER))
		do_script_cmd(NEXTCOMMAND);

	    while( reqwinup &&  
		   ((NewMessage = (struct IntuiMessage *)
				  GetMsg(reqwindow->UserPort)) != FALSE)
		 ) {
		class = NewMessage->Class;
		ReplyMsg( NewMessage );
		switch( class ) {
		    case REQCLEAR:
		    numreqs = 0;
		    break;

		    case CLOSEWINDOW:
		    KillReq(); /* Kills requester window, set reqwinup = 0 */
		    break;

		    case NEWSIZE:
		    ReqNewSize(reqwindow->Height, reqwindow->Width);
		    break;
		}   /* end of switch (class) */
	    } /* end while */
    }  /* end while ( keepgoing ) */

    /*   It must be time to quit, so we have to clean
    *   up and exit.
    */

    cleanup("",0);

} /* end of main */

/* cleanup code */

cleanup(reason, fault)
char *reason;
int fault;
    {
	extern struct Device *ConsoleDevice;	/* In init.c */
	extern struct IOStdReq ConReq;		/* In init.c */

    switch(fault) {
	case 0:		/* quitting close everything */
	KillReq();	/* Kill the requester and its window */
	ClearMenuStrip( mywindow );
	CloseDevice(&Audio_Request);
	UnLock(CurrentDir(StartLock));	/* back to original directory */

	case 8:		/* error opening audio */
	DeletePort(Audio_Port);
	FreeMem(BeepWave,BEEPSIZE);
	CloseDevice(&Timer);

	case 7:		/* error opening timer */
	DeletePort(Timer_Port);
	CloseDevice(&Script_Timer);
	DeletePort(Script_Timer_Port);

	case 6:		/* error opening write device */
	DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
	FreeMem(Write_Request,(long)sizeof(*Write_Request));
	CloseDevice(Read_Request);

	case 5:		/* error opening read device */
	DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
	FreeMem(Read_Request,(long)sizeof(*Read_Request));

	case 4:		/* error opening window */
	if (ConsoleDevice != NULL) CloseDevice(&ConReq);
	if (myfont   != NULL) CloseFont( myfont );
	if (mywindow != NULL) CloseWindow( mywindow );
	if (p_screen != 0) {
	    struct Process *mproc;

	    mproc = (struct Process *)FindTask(0L);
	    mproc->pr_WindowPtr = OrigWindowPtr;
	    CloseScreen( myscreen );
	}

	case 3:		/* error opening screen */
	case 2:		/* error opening graphics library */
	CloseLibrary(GfxBase);
	case 1:		/* error opening intuition */
	CloseLibrary(IntuitionBase);
	default:
	if (*reason) puts (reason);
	}
    exit(fault);
    }

do_capture(file)
char *file;
    {
    if (capture == TRUE)
	{
	capture=FALSE;
	fclose(tranr);
	InfoMsg1Line("End File Capture");
	}
    else
	{
	if (file == NULL || *file == '\0') {
	    name[0] = '\000';
	    req("Ascii Capture:",name,1);
	    }
	else strcpy(name, file);
	if ((tranr=fopen(name,"w")) == 0) {
	    capture=FALSE;
	    InfoMsg2Line("Error Opening File:", name);
	    return(FALSE);
	    }
	capture=TRUE;
	}
    redofile();
    }

do_send(file)
char *file;
    {
    if (send == TRUE)
	{
	send=FALSE;
	fclose(trans);
	InfoMsg1Line("File Send Cancelled");
	}
    else
	{
	if (file == NULL || *file == '\0') {
	    name[0] = '\000';
	    req("Ascii Send:",name,1);
	    }
	else strcpy(name, file);
	if ((trans=fopen(name,"r")) == 0) {
	    send=FALSE;
	    InfoMsg2Line("Error Opening File:", name);
	    return(FALSE);
	    }
	send=TRUE;
	}
    }

void setparams()
    {
    Read_Request->IOSer.io_Command =
	Write_Request->IOSer.io_Command =
	    SDCMD_SETPARAMS;
    DoIO(Read_Request); DoIO(Write_Request);
    Read_Request->IOSer.io_Command = CMD_READ;
    SendIO(Read_Request);
    Write_Request->IOSer.io_Command = CMD_WRITE;
    }

void hangup ()
    {
    if(!CheckIO(Read_Request))
	AbortIO(Read_Request);
    Wait (1L <<mySerPort->mp_SigBit);
    WaitIO(Read_Request);
    CloseDevice (Read_Request);
    Timer.tr_time.tv_secs=0L;
    Timer.tr_time.tv_micro=750000L;
    DoIO((char *) &Timer.tr_node);
    OpenDevice (SERIALNAME,(LONG)p_unit,Read_Request,NULL);
    setparams();
    }

void redocomm() {
    ClearMenuStrip( mywindow );         /* Remove old menu */
    InitCommItems();                    /* Re-do comm menu   */
    SetMenuStrip(mywindow,&menu[0]);    /* Re-display the menu */
}
void redofile() {
    ClearMenuStrip( mywindow );         /* Remove old menu */
    InitFileItems();                    /* Re-do file menu   */
    SetMenuStrip(mywindow,&menu[0]);    /* Re-display the menu */
}

void setserbaud(baud, redomenu)
int baud;
LONG redomenu;
    {
    if(!CheckIO(Read_Request))
	AbortIO(Read_Request);
    Wait (1L <<mySerPort->mp_SigBit);
    WaitIO(Read_Request);
    Write_Request->io_Baud = Read_Request->io_Baud = baud;
    setparams();
    p_baud = baud;
    if (redomenu) redocomm();
    }

void redoutil() {
    ClearMenuStrip(mywindow);
    InitUtilItems();
    SetMenuStrip(mywindow,&menu[0]);
    }

void handle_menupick(class, code)
ULONG class;
unsigned int code;
    {
    unsigned int menunum, itemnum, subnum, i;

    if (code == MENUNULL) return;

    menunum = MENUNUM( code );
    itemnum = ITEMNUM( code );
    subnum  = SUBNUM( code );
    switch( menunum ) {
    case 0:
	switch( itemnum ) {
	case 0:	/* menunum case 0 itemnum case 0 -- Set xfer mode */
	    switch( subnum ) {
	    case 0:	/* Ascii */
	    case 1:	/* Xmodem */
	    case 2:	/* XmodemCRC */
	    case 3:	/* Kermit */
		i = subnum;
		break;
	    default:
		i = MODEMAX-1;
	    }
	    p_xproto = i;
	    redofile();
	    break;

	case 1:	/* menunum case 0 itemnum case 1 -- Send a file */
	    name[0] = '\0';
	    cmd_sendf(name);
	    break;

	case 2:	/* menunum case 0 itemnum case 2 -- Receive a file */
	    name[0] = '\000';
	    cmd_recf(name);
	    break;

	case 3:	/* menunum case 0 itemnum case 3 -- Kermit GET */
	    name[0] = '\000';
	    cmd_kg(name);
	    break;

	case 4:	/* menunum case 0 itemnum case 4 -- Kermit BYE */
	    saybye();
	    break;
	case 5: /* menunum case 0 itemnum case 5 -- ASCII capture */
	    name[0] = '\0';
	    do_capture(name);
	    break;
	} /* End of itemnum switch for menunum case 0 */
	break;

    case 1:		/* menunum case 1 - Comm Setup */
	switch( itemnum ) {
	case 0:	/* Baud */
	    switch( subnum ) {
	    case 0:
		setserbaud(300, FALSE);
		break;

	    case 1:
		setserbaud(1200, FALSE);
		break;

	    case 2:
		setserbaud(2400, FALSE);
		break;

	    case 3:
		setserbaud(4800, FALSE);
		break;

	    case 4:
		setserbaud(9600, FALSE);
		break;
	    } /* End of subnum switch for itemnum 0 of menunum 1 */
	    break;

	case 1:    /* menunum case 1 itemnum 1 -- Set  Parity */
	    p_parity = subnum;
	    break;

	case 2:    /* menunum case 2 itemnum 2 -- set kermit transfer mode */
	    if (subnum < 2) p_mode = subnum;
	    else {
		if (p_convert)	p_convert = 0;
		else		p_convert = 1;
		redocomm();
	    }
	    break;
	}
	break;	/* End of menunum case 1 */

    case 2:	/* menunum case 2 - Script */
	if (!itemnum && !script_on) {
	    name[0] = '\000';
	    req("Script file name:",name,1);
	    script_start(name);
	}
	if (itemnum && script_on) exit_script();
	break;

    case 3:	/* menunum case 3 -- Utility */
	switch( itemnum ) {
	case 0:
	    sendbreak();
	    break;

	case 1:	/* menunum case 3 itemnum case 1 -- Hang Up */
	    hangup();
	    break;

	case 2:	/* menunum case 3 itemnum case 2 -- Cd */
	    strcpy(name,MyDir);
	    req("Directory:",name,1);
	    set_dir(name);
	    break;

	case 3:	/* menunum case 3 itemnum case 3 -- Clear Screen */
	    top = MINY; bot = MAXY; savx = MINX; savy = MINY;
	    curmode = FS_NORMAL; inesc = -1;
	    a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
	    redoutil();
	    emit(12);
	    break;

	case 4:	/* menunum case 3 itemnum case 4 -- Echo mode */
	    if (p_echo) p_echo = 0;
	    else	p_echo = 1;
	    redoutil();
	    break;

	case 5:	/* menunum case 3 itemnum case 5 -- Wrap mode */
	    if (p_wrap) p_wrap = 0;
	    else        p_wrap = 1;
	    redoutil();
	    break;

	case 6:	/* menunum case 3 itemnum case 6 -- NumKey */
	    if (p_keyapp) p_keyapp = 0;
	    else          p_keyapp = 1;
	    redoutil();
	    break;

	case 7:	/* menunum case 3 itemnum case 7 -- App Cur */
	    if (p_curapp) p_curapp = 0;
	    else	  p_curapp = 1;
	    redoutil();
	    break;

	case 8:	/* menunum case 3 itemnum case 8 -- BS <-> DEL */
	    swap_bs_del();
	    redoutil();
	    break;

	case 9:	/* menunum case 3 itemnum case 9 -- Xfer Beep */
	    if(p_xbeep) p_xbeep = 0;
	    else	p_xbeep = 1;
	    redoutil();
	    break;
	}

    break;
    } /* end of switch ( menunum ) */
}
