/********************************************************************
 *  vt100 terminal emulator with xmodem transfer capability
 *
 *	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 */
#define MODULE_MAIN 1
#include "vt100.h"

/******************************************************/
/*                   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;
    unsigned int code;
    int KeepGoing,i,la,dola,actual;
    char c,*ptr;

    ptr = InitDefaults(argc,argv);
    InitDevs();
    InitFileItems();
    InitCommItems();
    InitScriptItems();
    InitUtilItems();
    InitMenu();
    SetMenuStrip(mywindow,&menu[0]);

    MyDir[0]  =	    '\000';
    KeepGoing =	    TRUE;
    capture   =	    FALSE;
    send      =	    FALSE;
    maxcol    =	    MAXX / 8;
    la	      =	    0;
    x	      =	    MINX ; 
    y	      =	    MINY; 
    curmode   =	    FS_NORMAL;
    keyapp    =	    0;
    curapp    =	    0;
    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 (script_wait)	/* if script ready dont wait here */
		Wait(
		 (1L << mySerPort->mp_SigBit) |
		 (1L << mywindow->UserPort->mp_SigBit) |
		 (1L << Script_Timer_Port->mp_SigBit));
	    cursorflip();
	    
	    /* do ascii file send */
	    if (send)
		{
		if ((c=getc(trans)) != EOF) {
		    if (c == '\n') c = '\r';
		    sendchar(c);
		    }
		else {
		    fclose(trans);
		    emits("\nFile Sent\n");
		    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;
		ReplyMsg( NewMessage );
		switch( class )
		    {
		    case CLOSEWINDOW:
		    KeepGoing = FALSE;
		    break;

		    case RAWKEY:
		    c = toasc(code,0);
		    break;

		    case NEWSIZE:
		    emit(12);
		    break;

		    case MENUPICK:
		    handle_menupick(class,code);
		    break;				    
		    }   /* end of switch (class) */
		}   /* end of while ( newmessage )*/

            if (!script_wait || 
                 (CheckIO(&Script_Timer) && 
		    script_wait == WAIT_TIMER))
		do_script_cmd(NEXTCOMMAND);
	    }  /* 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;
    {
    switch(fault) {
	case 0:		/* quitting close everything */
	ClearMenuStrip( mywindow ); 
	CloseDevice(&Audio_Request);

	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));
	CloseWindow( mywindow );

	case 4:		/* error opening window */
	if (p_screen != 0) CloseScreen( myscreen );

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

do_capture(file)
char *file;
    {
    if (capture == TRUE)
        {
        capture=FALSE;
        fclose(tranr);
        emits("\nEnd File Capture\n");
        }
    else
        {
        if (file == NULL) {
            emits("\nAscii Capture:");
            filename(name);
	    } 
	else strcpy(name, file);
        if ((tranr=fopen(name,"w")) == 0) {
	    capture=FALSE;
	    emits("\nError Opening File\n");
	    return(FALSE);
	    }
	capture=TRUE;
        }
    }

do_send(file)
char *file;
    {
    if (send == TRUE)
	{ 
        send=FALSE;
        fclose(trans);
        emits("\nFile Send Cancelled\n");
        }
    else
        {
        if (file == NULL) {
            emits("\nAscii Send:");
            filename(name);
            }
	else strcpy(name, file);
        if ((trans=fopen(name,"r")) == 0) {
   	    send=FALSE;
	    emits("\nError Opening File\n");
	    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 ()
    {
    AbortIO(Read_Request);
    CloseDevice (Read_Request);
    Timer.tr_time.tv_secs=0L;
    Timer.tr_time.tv_micro=750000L;
    DoIO((char *) &Timer.tr_node);
    OpenDevice (SERIALNAME,NULL,Read_Request,NULL);
    setparams();
    }

void setserbaud(baud, redomenu)
int baud;
LONG redomenu;
    {
    AbortIO(Read_Request);
    Write_Request->io_Baud = Read_Request->io_Baud = baud;
    setparams();
    p_baud = baud;
    if (redomenu) {
	ClearMenuStrip( mywindow );         /* Remove old menu */
	InitCommItems();                    /* Re-do comm menu   */
	SetMenuStrip(mywindow,&menu[0]);    /* Re-display the menu */	
	}
    }

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

    if (code == MENUNULL) return;

    menunum = MENUNUM( code );
    itemnum = ITEMNUM( code );
    subnum  = SUBNUM( code );
    switch( menunum ) {
	case 0:
	switch( itemnum ) {
	    case 0:
	    do_capture(NULL);
	    break;

	    case 1:
	    do_send(NULL);
	    break;

	    case 2:
	    if (p_parity > 0) {
		emits("\nParity setting prevents this\n");
		break;
		}
	    emits("\nXmodem Receive:");
	    filename(name);
	    multi_xfer(name,XMODEM_Read_File,0);
	    break;

	    case 3:
	    if (p_parity > 0) {
		emits("\nParity setting prevents this\n");
		break;
		}
	    emits("\nXmodem Send:");
	    filename(name);
	    multi_xfer(name,XMODEM_Send_File,1);
	    break;

	    case 4:
	    server = TRUE;
	    emits("\nKermit GET remote file(s):");
	    filename(name);
	    multi_xfer(name,dokreceive,0);
            break;

	    case 5:
	    multi_xfer("",dokreceive,0);
	    break;

	    case 6:
	    server = TRUE;
	    emits("\nKermit Send local name:");
	    filename(name);
	    multi_xfer(name,doksend,1);
	    break;

	    case 7:
	    saybye();
	    break;
	    }
	break;

	case 1:
	switch( itemnum ) {
	    case 0:
	    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;
		}
	    break;	    

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

	    case 2:
	    /* set transfer mode */
	    p_mode = subnum;
	    break;
	    }
	break;

	case 2:
	if (!itemnum && !script_on) {
	    emits("Script file name: ");
	    filename(name);
	    script_start(name);
	    }
	if (itemnum && script_on) exit_script();
	break;

	case 3:
	switch( itemnum ) {
	    case 0:
	    sendbreak();
	    break;

	    case 1:
	    hangup();
	    break;

	    case 2:
	    emits("\nDirectory [");
	    emits(MyDir);
	    emits("]: ");
	    filename(name);
	    set_dir(name);
	    break;
	    }

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

