/*      EXAMPLE.C     */
/*-------------------------------------------------------*/
/*   Here is an example communications program that      */
/*   dials the Lattice BBS and offers a simple terminal  */
/*   emulator so you can interact with the BBS.  If you  */
/*   want to download a file, tell the BBS which file    */
/*   you want and then press the minus key.  You will    */
/*   be prompted to enter a command to this program to   */
/*   tell it what to do.                                 */
/*                                                       */
/*   The comments in the program are expressly designed  */
/*   to help you become familiar with using the Lattice  */
/*   Communications Library.                             */
/*-------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <proto/exec.h>
#include <proto/intuition.h>

#include <comm.h>                  /* don't forget this! */


#define BACKSPACE 8

void    main(int, char *[]);            /* prototype for our main routine   */
void    process_command(COMPORT);       /* prototype for command routine    */
extern int  _GetKey(COMPORT, UBYTE *);  /* prototype for single char input  */
                                        /*   (found in the Comm. Library)   */

int     done = 0;                  /* set to 1 if command is "quit" */

struct IntuitionBase *IntuitionBase;   /*  We need this for single  */
                                       /*  character input.         */


void main(argc, argv)
    int     argc;
    char    *argv[];
{
    COMPORT   com;
    int       ch     = 0;
    int       result = 0;
    int       len;
    char      chbuff[16];
    unsigned long   old_flags;


    /*  First we will open the intuition library so that   */
    /*  we will be able to get single character input      */
    /*  later on.  We will call the same routines that     */
    /*  the Lattice Communications Library uses to get     */
    /*  single character input.                            */

    IntuitionBase = (struct IntuitionBase *)
                          OpenLibrary("intuition.library", 33L);
    if (IntuitionBase == NULL) {
	printf("Could not open Intuition Library.  Aborting.\n");
	exit(1);
    }


    printf("\nOpening the serial port.\n");
    printf("Settings:  Baud rate 2400, 8 data bits, no parity, 1 stop bit.\n");
    printf("Buffer size is set to 4K\n\n");

    /*  If you want to use a baud rate other than 2400,  change the    */
    /*  third parameter.  If you want to use a serial port other than  */
    /*  the built-in one, change "serial.device" to the name of the    */
    /*  device driver which handles the port and set the port number   */
    /*  to the proper port you desire.                                 */

    com = ComOpen("serial.device", 1, 2400L, 8, NO_PARITY, 1, 4000, 1, NULL);
    if (com == NULL) {
        printf("Error opening the serial port.  Aborting.\n");
        exit(1);
    }


    /*  We'll wait up to 30 seconds for a connection to be made.   */
    /*  ComDialTime is part of the COMPORT structure which is      */
    /*  defined in comm.h (default is 60).                         */

    com->ComDialTime = 30;

    printf("Now dialing the Lattice BBS...\n");
    result = ComDial(com, "916-1200");

    if (result == -1) {
        printf("No connection after %d seconds.\n", com->ComDialTime);
        ComClose(com);
        exit(1);
    }

    if (result == 0) {
        printf("You pressed ESC; dialing interrupted.  Aborting.\n");

        /*   The following isn't strictly necessary here, but it   */
        /*   shows how to get rid of unwanted incoming characters  */

        ComFlush(com);

        ComClose(com);
        exit(1);
    }


    /*   At this point, since ComDial() succeeded, we know   */
    /*   that we have a connection between the two modems.   */

    printf("We're logged on!  Let's go into dumb-terminal mode.\n");
    printf("Press the minus key (-) to enter a command.\n\n\n");


    /*  The following is a fairly typical dumb-terminal emulation.   */
    /*  Incoming characters from the remote computer are displayed.  */
    /*  Keypresses in the ASCII range 1-127 are sent to the remote   */
    /*  computer, except for "-" (minus) keys, which we use as a     */
    /*  signal that a command is to be entered.                      */


    /*  Set our window to receive only raw keystroke events.  */
    /*  ComOpen() has found our CLI window, so we can just    */
    /*  use this window.                                      */

    old_flags = com->ComWindow->IDCMPFlags;
    ModifyIDCMP(com->ComWindow, RAWKEY);


    while (! done) {

        /*  Let's be ultra-conservative and check continuously to    */
        /*  see if the connection is still active.  We could check   */
        /*  less often (at strategic points), if we wished.          */

        if (! ComCarrier(com)) {
            printf("\nConnection was lost!  Aborting.\n");
            done++;
            continue;
        }


        /*  If there's a keypress, and it's not a "-", send it    */
        /*  to the remote computer.  _GetKey() handles all keys   */
	/*  and uses the current keymap.  The character buffer    */
	/*  passed to it MUST be at least 16 bytes long.          */

        len = _GetKey(com, chbuff);
        if (len > 0) {
            if (len == 1 && ch == '-')
                process_command(com);
            else
                ComWrite(com, chbuff, len);
        }

    /*  ComGetc() returns an int, not a char value.  -1 means that        */
    /*  there is no incoming character.  Anything else is cast as a char  */
    /*  and displayed on the screen.                                      */

        while ((ch = ComGetc(com)) != -1)
            putchar((char) ch);

        fflush(stdout);         /*  make sure we display the characters  */
    }


    /* The 'done' flag became true, and so we wind up here. */

    printf("\nClosing the communications port.\n");

    ModifyIDCMP(com->ComWindow, old_flags);
    ComClose(com);
    CloseLibrary((struct Library *) IntuitionBase);

    printf("All done.  Program ended.\n");


    exit(0);
}




void  process_command(com)
    COMPORT  com;
{
    int     result;

    char    filename[101];      /*  when you enter a filename for a  */
                                /*  transfer, it will go here.       */

    char    command[101];       /*  for the commands you enter.      */


    printf("\nAvailable commands are ");
    printf("'quit', 'hangup', 'send ymodem', and 'receive ymodem'. \n");
    printf("Enter command: ");
    fflush(stdout);

    gets(command);
    if (strlen(command) == 0)
        return;

    strlwr(command);

    if (strcmp(command, "quit") == 0) {
        done = 1;
        return;
    }


    /* It's easy to hang up the phone... */

    if (strcmp(command, "hangup") == 0) {
        printf("Hanging up....\n");
        result = ComDisc(com);
        printf("Result from hangup = %d\n", result);
        return;
    }


    /* It's just as easy to send a file... */

    if (strcmp(command, "send ymodem") == 0) {
        printf("Enter filename to send: ");
        gets(filename);
        printf("%d YModem blocks to be sent.\n", ComSizeY(filename));
        result = ComSendY(com, filename);
        printf("Result from YModem send = %d\n", result);
        return;
    }


    /* ...and how hard can it be to receive a file? */

    if (strcmp(command, "receive ymodem") == 0) {
        printf("Receive as what filename? ");
        gets(filename);
        result = ComRecvY(com, filename);
        printf("Result from YModem receive = %d\n", result);
        return;
    }


    printf("Invalid command.  Returning to terminal mode.\n");

    return;
}
