home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 019.lha / Aterm / aterm.c < prev    next >
C/C++ Source or Header  |  1986-11-10  |  21KB  |  842 lines

  1. /************************************************************************
  2. *  a terminal program that has ascii and xmodem transfer capability
  3. *
  4. *  originally written by Michael Mounier
  5. *
  6. * See file Aterm.mods for modification history.
  7. *
  8. ************************************************************************/
  9.  
  10.  
  11. /*  compiler directives to fetch the necessary header files */
  12. #include <libraries/dos.h>
  13. #include <devices/serial.h>
  14. #include <fcntl.h>
  15.  
  16. #include <exec/types.h>
  17. #include <stdio.h>
  18. #include <intuition/intuition.h>
  19. #include <intuition/intuitionbase.h>
  20. #include <exec/memory.h>
  21. #include <functions.h>
  22. #include "Options.h"
  23. #include "ConsoleIO.h"
  24. #include "SerialIO.h"
  25. #include "Timer.h"
  26.  
  27. #define INTUITION_REV 0L /* Use Current Version */
  28. #define GRAPHICS_REV  0L /* Use Current Version */
  29. #define VERSION  "Aterm 7.3"
  30. #define CSI     '\x9b'        /* command sequence introducer */
  31. #define EOS      '\0'         /* end of string marker        */
  32. #define CTRLN    ('N'&0x1f)
  33. #define    CHATON8    ("\x9b3S\x9b22;1H\x9b1K\x9b21;1H\x9b21t")
  34. #define CHATON9    ("\x9b3S\x9b19;1H\x9b1K\x9b18;1H\x9b18t")
  35. #define    CHOFF8    ("\x9b24t")
  36. #define CHOFF9    ("\x9b21t")
  37. #define WIPECH    ("\x9b3T\x9b3S")
  38.  
  39. /* External variables declared here */
  40.  
  41. #define NUMKEYS       10
  42. #define KEYSIZE       40
  43. #define BUFSIZE    KEYSIZE * NUMKEYS
  44. UBYTE   *KeyBuf  = NULL;    /* The Key Buffer */
  45. BOOL    chatting = FALSE;
  46. BOOL    DoPrefs  = TRUE;
  47. BOOL    StartClock();
  48. void    DeleteClock();
  49.  
  50. /* Intuition always wants to see these declarations */
  51.  
  52. struct IntuitionBase *IntuitionBase = NULL;
  53. struct GfxBase *GfxBase = NULL;
  54.  
  55. /* Global variables local to this module */
  56.  
  57. static UBYTE name[ 32 ];
  58. static BOOL  capture = FALSE;
  59. static BOOL  sending = FALSE;
  60. static BOOL  waiting = FALSE;
  61. static FILE  *tranr, *trans;
  62. static BOOL  ClockON = FALSE;
  63. static ULONG waitmask;
  64. static LONG  maxcount;
  65.  
  66. /* Defaults if no "Init.key" file. */
  67. static struct options Options =
  68.     {
  69.       /* Baud      */  300,
  70.       /* Mode      */  MODEFULL,
  71.       /* AutoChop  */  TRUE,
  72.       /* Xon       */  FALSE,
  73.       /* Protocol  */  XMODEMCRC,
  74.       /* Prompt    */  EOS     /* None */
  75.      } ;
  76.  
  77. static int baudrate[] = { 300,1200,2400,4800,9600 };
  78.  
  79. static struct Preferences *Preferences;
  80. static struct IOExtSer *SerialIO = NULL;
  81. static struct IOStdReq *Console = NULL;    /* see "ConsoleIO.h"    */
  82. static BOOL   TimerOpened = FALSE;
  83.  
  84. /* my window structure */
  85. struct NewWindow NewWindow = {
  86.    0,0,640,200, /* left, top, width, height */
  87.    0,1,     /* detail, block pens */
  88.    CLOSEWINDOW | MENUPICK | GADGETUP,
  89.    WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDEPTH | BORDERLESS,
  90.    NULL,       /* firstgadget */
  91.    NULL,       /* checkmark */
  92.    (UBYTE *)VERSION, /* title */
  93.    0,           /* screen */
  94.    NULL,       /* bitmap */
  95.    0,0,        /* min x,y */
  96.    640, 200,   /* max x,y */
  97.    WBENCHSCREEN  /* type */
  98. };
  99.  
  100. static struct Window *mywindow = NULL;     /* ptr to applications window */
  101. static struct RastPort *rp;           /* ptr to RastPort for Chat   */
  102. static struct IntuiMessage *NewMessage;       /* msg structure for GetMsg() */
  103. static struct Menu *menuStrip = NULL;      /* from InitMenu()            */
  104.  
  105. /*--------------------------------------------------------------*/
  106. /*    cleanup: all done so close up and prepare to exit    */
  107. /*--------------------------------------------------------------*/
  108.  
  109. static void cleanup()
  110. {
  111.    if ( ClockON )
  112.     DeleteClock();
  113.    if ( KeyBuf != NULL )
  114.       FreeMem( KeyBuf, (long)BUFSIZE );
  115.    if ( TimerOpened )
  116.       CloseTimer();
  117.    if ( SerialIO != NULL )
  118.      CloseSerialIO();
  119.    if ( menuStrip != NULL )
  120.     CloseMenu();    
  121.    if ( mywindow != NULL )
  122.     CloseWindow( mywindow );
  123.    if ( Console != NULL )
  124.     CloseConsoleIO();
  125.    if ( GfxBase != NULL )
  126.       CloseLibrary( GfxBase );
  127.    if ( IntuitionBase != NULL )
  128.       CloseLibrary(IntuitionBase);
  129. }
  130.  
  131. /*--------------------------------------------------------------*/
  132. /*    setdefaults: set defaults occording to current options. */
  133. /*--------------------------------------------------------------*/
  134.  
  135. static void setdefaults()
  136. {
  137.    /* set defaults */
  138.  
  139. if (DoPrefs)
  140.   {
  141.    switch ( Preferences->BaudRate )
  142.      {
  143.     case 1:
  144.      Options.Baud = 300;
  145.      break;
  146.     case 2:
  147.      Options.Baud = 1200;
  148.      break;
  149.     case 3:
  150.      Options.Baud = 2400;
  151.      break;
  152.     case 4:
  153.      Options.Baud = 4800;
  154.      break;
  155.     case 5:
  156.      Options.Baud = 9600;
  157.      break;
  158.     default:
  159.      Options.Baud = 300;
  160.      break;
  161.      }
  162.   }
  163.    
  164.    SetSerBaud( (int)Options.Baud);
  165.    SetSerMode( (int)Options.Mode);
  166.    SetXonMode( (BOOL)Options.Xon );
  167.    SetMenu( &Options );
  168.    DoPrefs = FALSE;
  169. }
  170.  
  171. /*--------------------------------------------------------------*/
  172. /*    init: initialize Aterm - set defaults            */
  173. /*--------------------------------------------------------------*/
  174.  
  175. static void init()
  176. {
  177.    extern struct Menu *InitMenu();
  178.    static char initkeyname[] = "s:init.key";
  179.    char *s;
  180.    BOOL   initFound;
  181.    int      j;
  182.  
  183.     static char *credits[] =
  184.    {"\x9b8y\xC\x9B33m\x9B5;17HA T E R M   V E R S I O N   7.3",
  185.     "\x9B7;19HOriginal by Michael Mounier",
  186.     "\x9B9;21HMajor Modifications by:",
  187.     "\x9B10;26HJeff Lydiatt",
  188.     "\x9B11;22HLarry Phillips (ICUG)",
  189.     "\x9B12;27HSteve Allen",
  190.     "\x9B14;24HSpecial Thanks to",
  191.     "\x9B16;14H\x9B3mThe Independent Computer Users Group\x9B0;33m",
  192.     "\x9B17;30Hand",
  193.     "\x9B18;14H\x9B3mThe Source Telecomputing Corporation\x9B0;33m"
  194.     "\x9B20;8HWho Made the Super Kermit Implementation Possible"
  195.     "\x9Bm",
  196.     NULL};
  197.  
  198.    IntuitionBase = (struct IntuitionBase *) 
  199.                     OpenLibrary("intuition.library", INTUITION_REV);
  200.    if( IntuitionBase == NULL )
  201.       {
  202.     puts("can't open intuition\n");
  203.      goto badopen;
  204.       }
  205.  
  206.    Preferences = GetPrefs (Preferences, 4L);
  207.  
  208.    GfxBase = (struct GfxBase *) 
  209.               OpenLibrary("graphics.library", GRAPHICS_REV);
  210.    if( GfxBase == NULL )
  211.       {
  212.      puts("can't open graphics library\n");
  213.      goto badopen;
  214.       }
  215.    
  216.    if ( (TimerOpened = OpenTimer()) == FALSE )
  217.       {
  218.     puts( "Can't open the Timer." );
  219.     goto badopen;
  220.       }
  221.  
  222.    if(( mywindow = OpenWindow(&NewWindow) ) == NULL)
  223.       {
  224.     puts("Can't open a window.\n");
  225.     goto badopen;
  226.       }
  227.  
  228.    if(( Console = InitConsoleIO( mywindow ) ) == NULL)
  229.       {
  230.     puts("Can't open the console.\n");
  231.     goto badopen;
  232.       }
  233.  
  234.    if(( SerialIO = InitSerialIO() ) == NULL)
  235.       {
  236.     puts("Can't open the Serial Port.\n");
  237.     goto badopen;
  238.       }
  239.  
  240.    if (( KeyBuf= AllocMem( (long)BUFSIZE,
  241.      (long)MEMF_PUBLIC | MEMF_CLEAR))== NULL)
  242.       {
  243.     puts("Can't get memory for function keys.\n");
  244.     goto badopen;
  245.       }
  246.  
  247.    menuStrip = InitMenu( mywindow );
  248.  
  249.    j = 0;
  250.    while ( (s = credits[j++]) != NULL )
  251.       PutString( s );
  252.  
  253.    CursorXY(1, 1);
  254.    if ( (ClockON = StartClock( mywindow )) == TRUE )
  255.       PutString( "\x9b33mClock Task Started.\n\x9bm" );
  256.  
  257.    initFound = LoadKeys( initkeyname );        /* did the default f-keys load? */
  258.    if ( LoadKeys( &initkeyname[2] ) )
  259.       initFound = TRUE;
  260.    if ( initFound )
  261.     PutString( "\x9b33mFunction Keys Loaded...\n\x9bm" );
  262.    else
  263.       setdefaults();
  264.  
  265.    rp = mywindow->RPort;
  266.  
  267.    CursorXY(1, 22);
  268.    return;
  269.  
  270. badopen:
  271.    cleanup();
  272.    exit( 4 );
  273. }
  274.  
  275. /*--------------------------------------------------------------*/
  276. /*    SetOptions: called by LoadKeys to replace all options.  */
  277. /*--------------------------------------------------------------*/
  278.  
  279. void SetOptions( opt, optsize )
  280. register char *opt;
  281. int optsize;
  282. {
  283.    register int i;
  284.    register char *s;
  285.  
  286.    /* Note future changes can be easily accomplished by testing */
  287.    /* for the optsize of the older versions, and making the     */
  288.    /* appropriate defaults and/or sending an error message.    */
  289.    
  290.    if (optsize != sizeof( Options ) )
  291.      {
  292.        optsize = sizeof( Options );
  293.        PutString( "Can't happen: setoptions got a bad option size." );
  294.        if ( optsize > sizeof( Options ) )
  295.       optsize = sizeof( Options );
  296.      }
  297.  
  298.    /* copy the options */
  299.    /* The trick here is to pretend Options is an array of chars */
  300.    /* for the purpose of copying the options passed by LoadKeys */
  301.  
  302.    s = (char *)&Options.Baud;
  303.    for (i = 0; i < optsize; i++)
  304.       *s++ = *opt++;
  305.  
  306.    setdefaults();
  307. }
  308.  
  309. /*--------------------------------------------------------------*/
  310. /*    GetOptions: called by SaveKeys to store current options.*/
  311. /*--------------------------------------------------------------*/
  312.  
  313. int GetOptions( opt, maxsize )
  314. register char *opt;
  315. int maxsize;
  316. {
  317.    register int i;
  318.    register char *s;
  319.  
  320.    if (maxsize > sizeof( Options ) )
  321.       maxsize = sizeof( Options );
  322.  
  323.    /* copy the options */
  324.    /* Note the same trick of treating Options as an array of chars*/
  325.    /* is used here to copy the current options to a workspace     */
  326.    /* provided by SaveKeys.                                       */
  327.  
  328.    s = (char *)&Options.Baud;
  329.    for (i = 0; i < maxsize; i++)
  330.       *opt++ = *s++;
  331.  
  332.    return sizeof( Options );
  333. }
  334. static void GetFunc(s)
  335. char *s;
  336. {
  337.     char name[40];
  338.  
  339.     strcpy(name, "s:");
  340.     strcat(name,s);
  341.  
  342.     if (LoadKeys(&name[2]))
  343.        PutString("\x9b33mLoaded\n\x9bm");
  344.     else if (LoadKeys(&name[0]))
  345.        PutString("\x9b33mLoaded\n\x9bm");
  346.     else
  347.        PutString("\x9b33mCouldn't load that file\n\x9bm");
  348. }
  349.  
  350. /*--------------------------------------------------------------*/
  351. /*          doFileMenu: Handle Menu 0                     */
  352. /*--------------------------------------------------------------*/
  353. static void doFileMenu( itemnum, subnum )
  354. int itemnum, subnum;
  355. {
  356.    UBYTE c;
  357.    BOOL  status;
  358.  
  359.    switch( itemnum )
  360.      {
  361.        /*-----------------------------------*/
  362.        /*     Ascii Receive            */
  363.        /*-----------------------------------*/    
  364.        case 0:
  365.     if (capture)
  366.       {
  367.          capture = FALSE;
  368.          fclose(tranr);
  369.          PutString("\x9b33m\nEnd File Capture\n\x9bm");
  370.           }
  371.     else
  372.           {
  373.          if ( !GetLine("\x9b33m\nAscii Capture: ", name))
  374.             PutString("\nAborted\n\x9bm");
  375.          else
  376.                {
  377.            if ((tranr=fopen(name,"w")) == 0)
  378.              {
  379.             capture=FALSE;
  380.             PutString("\nCan't Open File\n\x9bm");
  381.             break;
  382.              }
  383.           capture = TRUE;
  384.           PutString("\x9bm");
  385.            }
  386.        }
  387.     break;
  388.  
  389.        /*-----------------------------------*/
  390.        /*     Ascii Send            */
  391.        /*-----------------------------------*/    
  392.         case 1:
  393.     if (sending)
  394.       { 
  395.          sending = waiting = FALSE;
  396.          fclose(trans);
  397.          PutString("\n\x9b33mFile Send Cancelled\n\x9bm");
  398.        }
  399.      else if ( !GetLine("\x9b33m\nAscii Send: ",name) )
  400.         PutString("\nAborted\n\x9bm");
  401.     else if ( (trans = fopen(name,"r")) == 0)
  402.        {
  403.           sending = FALSE;
  404.           PutString("\nCan't Open File\n\x9bm");
  405.         }
  406.     else
  407.         {
  408.           sending = TRUE;
  409.           waiting = FALSE;
  410.            PutString("\x9bm");
  411.         }
  412.     break;
  413.  
  414.        /*-----------------------------------*/
  415.        /*     Binary Receive            */
  416.        /*-----------------------------------*/    
  417.        case 2:
  418.     if ( !GetLine("\x9b33m\nBinary Receive: ", name))
  419.       PutString("\nAborted\n\x9Bm");
  420.     else
  421.       {
  422.         if ( Options.Protocol == KERMIT )
  423.         status = KermitGet( name );
  424.         else
  425.           {
  426.         /* disable ^Q/^S trapping */
  427.         PushSerState();
  428.         SetXonMode( FALSE );
  429.         status = XMODEM_Read_File(name,
  430.                         (BOOL)(Options.Protocol == 1), (BOOL)Options.AutoChop);
  431.         PullSerState();
  432.           }
  433.         if ( status )
  434.         PutString("\nFile Received\n\x9bm");
  435.         else
  436.         PutString("\nBinary Receive Failed\n\x9bm");
  437.         DisplayBeep(NULL);
  438.       }
  439.     break;
  440.  
  441.        /*-----------------------------------*/
  442.        /*     Binary Send            */
  443.        /*-----------------------------------*/    
  444.        case 3:
  445.     if ( !GetLine("\x9b33m\nBinary Send: ",name))
  446.        PutString("\nAborted\n\x9bm");
  447.     else
  448.       {
  449.         if ( Options.Protocol == KERMIT )
  450.            status = KermitPut( name );
  451.         else
  452.            status = XMODEM_Send_File( name, (int)Options.Baud );
  453.         if ( status )
  454.         PutString("\nFile Sent\n\x9bm");
  455.          else
  456.         PutString("\nBinary Send Failed\n\x9bm");
  457.         DisplayBeep(NULL);
  458.  
  459.       }
  460.     break;
  461.  
  462.        /*-----------------------------------*/
  463.        /*     Prompt                */
  464.        /*-----------------------------------*/    
  465.        case 4:
  466.     PutString("\x9b33m\nNew Prompt Character: ");
  467.     if ( (c = GetKey()) == '0')
  468.         Options.Prompt = EOS;
  469.     else 
  470.        Options.Prompt = c;
  471.     keychar( c );
  472.     PutString("\n\x9bm");
  473.         break;
  474.     }
  475. }
  476.  
  477. /*----------------------------------------------------------*/
  478. /*  doMiscMenu: Handle the miscellaneous menus            */
  479. /*----------------------------------------------------------*/
  480. static void doMiscMenu( itemnum, subnum )
  481. int itemnum, subnum;
  482. {
  483.    switch (itemnum)
  484.      {
  485.        /*---------------------------------*/
  486.        /*       FKey Load          */
  487.        /*---------------------------------*/
  488.        case 0: /* FKey load */
  489.     if ( !GetLine("\x9b33m\nFunction-Key file name: ",name))
  490.        PutString(" aborted.\n\x9bm");
  491.     else
  492.       { 
  493.         GetFunc(name);
  494.       }
  495.     break;
  496.  
  497.        /*---------------------------------*/
  498.        /*       FKey Save          */
  499.        /*---------------------------------*/
  500.        case 1:
  501.     if ( !GetLine("\x9b33m\nFunction-Key Save Filename: ",name))
  502.        PutString( "aborted...\n\x9bm" );
  503.     else
  504.       {
  505.         if (SaveFKeys(name))
  506.            PutString( "File saved\n\x9bm" );
  507.         else
  508.            PutString( "Unable to save that file.\n\x9bm" );
  509.       }
  510.     break;
  511.  
  512.        /*---------------------------------*/
  513.        /*       define an FKey          */
  514.        /*---------------------------------*/
  515.        case 2:
  516.     DefineString();
  517.     break;
  518.  
  519.        /*---------------------------------*/
  520.        /*       Toggle AutoChop          */
  521.        /*---------------------------------*/
  522.        case 3:
  523.     Options.AutoChop = (subnum == 0);
  524.     break;
  525.  
  526.        /*---------------------------------*/
  527.        /*       Toggle Xon Mode          */
  528.        /*---------------------------------*/
  529.        case 4:
  530.     Options.Xon = (subnum == 0);
  531.     SetXonMode( (BOOL)Options.Xon );
  532.     break;
  533.  
  534.        /*---------------------------------*/
  535.        /*    Set Protocol          */
  536.        /*---------------------------------*/
  537.        case 5:
  538.     Options.Protocol = subnum;
  539.     break;
  540.  
  541.        /*---------------------------------*/
  542.        /*      CHAT Mode toggle           */
  543.        /*---------------------------------*/
  544.        case 6:
  545.     chatting = !chatting;
  546.     Chat( chatting );
  547.     break;
  548.  
  549.        /*---------------------------------*/
  550.        /*    Do Phone Book          */
  551.        /*---------------------------------*/
  552.        case 7:
  553.      do_phlib( mywindow );
  554.     break;
  555.  
  556.     }
  557. }
  558. /*============================================================*/
  559. /*== CHAT functions. Moved here because I couldn't get them ==*/
  560. /*== working in a separate file.                ==*/
  561. /*============================================================*/
  562.  
  563. /*---------------------------------*/
  564. /* Chat - Turns CHAT window on/off */
  565. /*---------------------------------*/
  566.  
  567. Chat( flag )
  568. BOOL flag;
  569.  
  570. {
  571. char cursor = '_';
  572.  
  573. if (flag)
  574.   {
  575.     if (Preferences->FontHeight == 8)
  576.      {
  577.       PutString ( CHATON8 );
  578.       Move ( rp, 0L, 198L );
  579.       RectFill( rp, 0L, 178L, 640L, 181L);
  580.       maxcount = 79;
  581.      }
  582.     if (Preferences->FontHeight == 9)
  583.      {
  584.       PutString ( CHATON9 );
  585.       Move ( rp, 0L, 196L );
  586.       RectFill( rp, 0L, 173L, 640L, 176L);
  587.       maxcount = 63;
  588.      }
  589.     Text ( rp, &cursor, 1L );
  590.   }
  591. else
  592.   {
  593.     if (Preferences->FontHeight == 8)
  594.     PutString ( CHOFF8 );
  595.     if (Preferences->FontHeight == 9)
  596.      {
  597.     ScrollRaster( rp,0L, -20L,0L,180L,640L,200L );
  598.     PutString ( CHOFF9 );
  599.      }
  600.     PutString( WIPECH );
  601.     ChatOut  ( 0 );
  602.   }
  603. }
  604.  
  605. /*-----------------------------------------*/
  606. /* ChatOut - Send character to CHAT window */
  607. /*       - Send to SerIO if CR/LF        */
  608. /*-----------------------------------------*/
  609.  
  610. ChatOut( c )
  611. UBYTE c;
  612.  
  613. {
  614. static    LONG    count = 0;
  615. static    UBYTE    line[ 81 ] = '_';
  616.  
  617. int    i;
  618.  
  619. Move ( rp, 0L, 197L );
  620.  
  621. switch (c)
  622.      {
  623.     case '\r':
  624.     case '\n':
  625.       line[count] = '\r';
  626.       for ( i = 0; i < count; i++ )
  627.         SerIOPut(line[i]);
  628.       SerIOPut ('\r');
  629.       line[0] = '_';
  630.       count = 0;
  631.       if (Preferences->FontHeight == 8)
  632.         ScrollRaster( rp,0L,(LONG)Preferences->FontHeight,0L,183L,640L,200L );
  633.       if (Preferences->FontHeight == 9)
  634.         ScrollRaster( rp,0L,(LONG)Preferences->FontHeight,0L,181L,640L,200L );
  635.       Text( rp, line, 1L );
  636.      break;
  637.  
  638.     case '\x08':
  639.       if (count > 0)
  640.        {
  641.         line [count--] = ' ' ;
  642.         line [count]   = '_';
  643.         Text( rp, line, count+2 );
  644.        }
  645.       break;
  646.  
  647.     case '\0':
  648.       count   = 0;
  649.       line[0] = '_';
  650.     break;
  651.  
  652.     default:
  653.       if ( count < maxcount )
  654.        {
  655.         line[count++] = c;
  656.         line[count]   = '_';
  657.         Text( rp, line, count+1 );
  658.        }
  659.       else
  660.        PutChar('\x07');
  661.     break;
  662.      }
  663. }
  664.  
  665. /******************************************************/
  666. /*             Main Program              */
  667. /*                              */
  668. /*    This is the main body of the program.          */
  669. /******************************************************/
  670.  
  671. main()
  672. {
  673. ULONG class, waitmask;
  674. int code, menunum, itemnum, subnum;
  675. BOOL KeepGoing;
  676. int c, i;
  677. UBYTE character, *KeyOffset;
  678.  
  679.    init();
  680.  
  681.    waitmask = (1L << SerialIO->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
  682.            |  (1L << mywindow->UserPort->mp_SigBit)
  683.            |  (1L << Console->io_Message.mn_ReplyPort->mp_SigBit);
  684.  
  685.    KeepGoing = TRUE;
  686.    while( KeepGoing )
  687.      {
  688.  
  689.       if ( !sending || waiting )
  690.           Wait( waitmask );
  691.  
  692.        /* --- Ascii Send Routine interleaved ----------*/
  693.        if ( sending && !waiting /* for the Prompt character */ )
  694.          {
  695.        if ( (c = getc(trans)) == EOF)
  696.          {
  697.         fclose( trans );
  698.         PutString( "\x9b33m\nFile Sent\n\x9bm" );
  699.         sending = waiting = FALSE;
  700.          }
  701.        else if (c == '\n' )
  702.          {
  703.         SerIOPut('\r');  /* switch in carriage return    */
  704.         if ( Options.Prompt != EOS )
  705.             waiting=TRUE;
  706.          }
  707.        else SerIOPut(c);
  708.      } /* end (if sending) */
  709.  
  710.       /*-----  Drain the keyboard buffer--------------*/
  711.  
  712.       while ( c = CheckKey() )
  713.     {
  714.        if (c != CSI)
  715.         {
  716.           if (chatting)
  717.         ChatOut( c );
  718.           else
  719.         SerIOPut( c );
  720.         }
  721.        else
  722.          {
  723.         character = GetKey();
  724.         if ((character < 'A') || (character > 'D'))
  725.            while ( GetKey() != '~');
  726.  
  727.         if ( ('0' <= character) && (character <= '9') )
  728.           {
  729.             KeyOffset = KeyBuf + (KEYSIZE * (character - '0'));
  730.             while ( c = *KeyOffset++ )
  731.               {
  732.             if (CheckKey() == 27)
  733.               {
  734.                 PutString("\x9b33m\nFunction key aborted.\x9bm\n");
  735.                 break;
  736.               }
  737.             if ( c > 127 )
  738.               {
  739.                 switch (c)
  740.                   {
  741.                     case 128:        /* <LOAD> */
  742.                   GetFunc(KeyOffset);
  743.                   while (c = *KeyOffset++);
  744.                    KeyOffset--;
  745.                   break;
  746.                 case 129:        /* <LOADEX */
  747.                   c = *KeyOffset++;
  748.                   GetFunc(KeyOffset);
  749.                   KeyOffset=KeyBuf + (KEYSIZE * (c - '0' -1));
  750.                   break;
  751.                 default:
  752.                   if (( c > 129 ) && ( c < 140 )) /* <Fn:> */
  753.                     KeyOffset=KeyBuf+(KEYSIZE*(c - 83 - '0'));
  754.                   break;
  755.                   }            /* end case (c)   */
  756.               }            /* end if (c>127) */
  757.             else
  758.              SerIOPut( c );
  759.               }                /* end while */
  760.           }                /* end if    */
  761.         else if (character == '?')
  762.           {
  763.              PutString( "\x9b33m\n" ); /* in red */
  764.              PutString( VERSION );
  765.               PutString( "\n\nPrompt character is  " );
  766.              if ( Options.Prompt == EOS)
  767.             PutString( "Inactive" );
  768.              else
  769.             keychar( Options.Prompt );
  770.              PutString("\n\n");
  771.              DoContents();        /* display function keys */
  772.              PutString("\x9bm");    /* turn off red */
  773.           }
  774.  
  775.          }    /* end if CSI */
  776.     }   /* end while CheckKey() */
  777.  
  778.      /*----- Drain the Serial Port Buffer-------------*/
  779.  
  780.      if ( CheckSerIO() )
  781.         {
  782.       do
  783.         {
  784.           c = SerIOGet() & 0x7f;
  785.           if ((c != '\n') && (c != CTRLN))    /* don't print LF or CTRL N */
  786.           PutFormat(c=='\r'?'\n':c);    /* convert CR into LF */
  787.  
  788.           if ( (waiting) && (c == Options.Prompt) )
  789.              waiting = FALSE;
  790.           if (capture)
  791.              if ( (' ' <= c && c < '\x7f') || c == '\n' || c== '\t' )
  792.             putc( c, tranr ); /* trash them mangy ctl chars */
  793.         } while( CheckSerIO() );
  794.      PutFormat((UBYTE)'\xff');    /* squirt out all received chars */
  795.        }
  796.      
  797.      /* ---------------- Handle all Menu Messages --------------------*/
  798.  
  799.      while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
  800.     {
  801.       class = NewMessage->Class;
  802.       code = NewMessage->Code;
  803.       ReplyMsg( NewMessage );
  804.       switch( class )
  805.         {
  806.           case CLOSEWINDOW:
  807.            KeepGoing = FALSE;
  808.              break;
  809.  
  810.           case MENUPICK:
  811.            if (    code != MENUNULL )
  812.              {
  813.                menunum = MENUNUM( code );
  814.                itemnum = ITEMNUM( code );
  815.                subnum  =  SUBNUM( code ); 
  816.                switch( menunum )
  817.              {
  818.                case 0:
  819.                 doFileMenu( itemnum, subnum );
  820.                 break;
  821.                case 1:        /* New Baud Rate */
  822.                 Options.Baud = baudrate[ itemnum ];
  823.                 SetSerBaud( (int)Options.Baud );
  824.                 break;
  825.                 case 2:           /*  "Mode" */
  826.                 Options.Mode = itemnum;
  827.                 SetSerMode( (int)Options.Mode );
  828.                 break;
  829.  
  830.                 case 3:    /* misc. menu selection */
  831.                 doMiscMenu( itemnum, subnum );
  832.                 break;
  833.                 } /* end of switch ( menunum ) */
  834.                }    /*end of for( not MENUNULL ) */
  835.         }   /* end of switch (class) */
  836.      }   /* end of while ( newmessage )*/
  837.   }    /* end while ( keepgoing ) */
  838.  
  839.    cleanup();
  840.    exit( 0 );
  841. } /* end of main */
  842.