#include <stdio.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/serial.h>

#define MAX_CHARS 102
#define SECSIZ 0x80
#define TTIME 30
#define BufSize 0x1000
#define ERRORMAX 10
#define RETRYMAX 10
#define SOH 1
#define EOT 4
#define ACK 6
#define CTRLQ (char)17
#define CTRLS (char)19
#define NAK 21

static char bufr[BufSize];
static int fd, timeout = FALSE;
static long bytes_xferred;
static int oktosay = 1;

/*
 * External functions
 */
extern   unsigned char        *stpblk();
extern   unsigned char        *AllocMem();
extern   struct   MsgPort     *CreatePort();
extern   struct   FileHandle  *Open();

/*
 * forward references
 */
int   define_function_key(), end(), help(), offline(), online(), sb(), rb(),
      gfxoff(), speechon(), speechoff();
/*
 * Tables
 */
struct {
   unsigned char  *cmdname;
   int            (*cmdfunc)();
   } command_table[] = {
   (unsigned char *)"define", &define_function_key,
   (unsigned char *)"def", &define_function_key,
   (unsigned char *)"end", &end,
   (unsigned char *)"help", &help,
   (unsigned char *)"online", &online,
   (unsigned char *)"on", &online,
   (unsigned char *)"offline", &offline,
   (unsigned char *)"off", &offline,
   (unsigned char *)"gfxoff", &gfxoff,
   (unsigned char *)"sb", &sb,
   (unsigned char *)"rb", &rb,
   (unsigned char *)"speechon", &speechon,
   (unsigned char *)"speechoff", &speechoff,
   (unsigned char *)"\0", &help,
   };

unsigned char  *help_messages[] = {
   "sb         = send file using Xmodem",
   "rb         = receive file using Xmodem",
   "def        = define a function key",
   "define     = define a function key",
   "end        = exit the program",
   "help       = print this list",
   "online     = enter or re-enter terminal mode",
   "offline    = terminate communication",
   "gfxoff     = terminate graphics",
   "speechon   = permit speech",
   "speechoff  = forbid speech",
   0};

unsigned char  *function_key_definitions[20] = {
   0,0,0,0,0,0,0,0,0,0,
   0,0,0,0,0,0,0,0,0,0
   };

/*
 * Globals
 */
unsigned char     work[512];
unsigned char     buf[512];
unsigned char     iobuf[1024];
int num_of_chars, no_io;

/*
 * Terminal globals
 */
struct   FileHandle     *terminal_infp;
struct   FileHandle     *terminal_outfp;

/*
 * Terminal emulator stuff
 */
struct   Message        *mymessage;
struct   IOExtSer       *ModemReadRequest;
struct   IOExtSer       *ModemWriteRequest;

unsigned char  *WelcomeMessage = "Entering Terminal Mode\nUse ^C for command mode\n";
unsigned char  *GoodbyeMessage = "Disconnected\n";
unsigned char  *OfflineMessage = "--- Offline ---\n";
unsigned char  *OnlineMessage = "--- Online ---\n";

unsigned char     rs_in[2], rs_out[2];
int      bdoneflag = 0;
int      TermEcho = 0;
int      modem_online = 0;

static int gfx_flag;

main(argc, argv)
  int   argc;
  unsigned char  *argv[];
{
  gfx_flag = 0;
  num_of_chars = 0;
  no_io = 0;
  sprintf(work, "Raw:0/0/640/200/Terminal");
  terminal_infp = Open(work, MODE_NEWFILE);
  if (terminal_infp == 0) {
    printf("Can't open window\n");
    exit(1);
  }
  terminal_outfp = terminal_infp;
  sprintf(work, "\033[0x\033[0y\033[25t\033[80u\014");
  WriteWork();

  while (1) {
    Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
    getcommand(buf);
    CommandInterpreter(buf);
  }
}

WriteWork() {
  Write(terminal_outfp, work, strlen(work));
}

CommandInterpreter(command)
  unsigned char  *command;
{
  int   i;

  command = stpblk(command);
  /*
   * Scan through the command table for the string and invoke the function
   *    to do the actual work of the command.  Each of these commands is
   *    defined below, and the functions each take a pointer to the
   *    string containing the arguments passed the command line.
   */
  for (i=0; command_table[i].cmdname[0] != '\0'; i++)
    if (strncmp(command, command_table[i].cmdname,
                strlen(command_table[i].cmdname)) == 0) {
      (*command_table[i].cmdfunc)
        (stpblk(&command[strlen(command_table[i].cmdname)]));
      goto FinishedCommand;
    }
  /*
   * Not found, so look for it on the disk.
   */
  executive(stpblk(&command[0]));
FinishedCommand:
  ;  /* Labels MUST be attached to some statement; even if the null stmt */
}

executive(s)
  unsigned char  *s;
{
  if (!Execute(s, 0, terminal_outfp))
    printf("%d\n", IoErr());
}

define_function_key(s)
unsigned char  *s;
{
  int   i;

  if (s[0] == '\0')
    for (i=0; i<20; i++) {
      if (function_key_definitions[i]) {
        sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[i]);
        WriteWork();
      }
    }
  else if (s[0] == 'f' || s[0] == 'F') {
    s++;
    i = atoi(s);
    if (i < 1 || i > 20) {
      sprintf(work, "%c[36mInvalid function key%c[0m\n", 0x1b, 0x1b);
      WriteWork();
    } else {
      i--;
      if (function_key_definitions[i])
        FreeMem(function_key_definitions[i], strlen(function_key_definitions[i])+1);
      while (isdigit(*s))
        s++;
      s = stpblk(s);
      if (*s != '\0') {
        function_key_definitions[i] = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
        if (function_key_definitions[i] == 0) {
          sprintf(work, "%c[36mDefine Error: not enough memory%c[0m\n",
                  0x1b, 0x1b);
          WriteWork();
        } else
          strcpy(function_key_definitions[i], s);
      }
    }
  } else {
    sprintf(work,
            "%c[36mDefine Error: invalid function key specified%c[0m\n",
            0x1b, 0x1b);
    WriteWork();
  }
}

end(s)
  unsigned char  *s;
{
  if (modem_online) {
    sprintf(work, "%c[36mTerminal Mode Error: Modem still online%c[0m\n",
            0x1b, 0x1b);
    WriteWork();
  } else {
    if (gfx_flag == 1)
      terminate();
    Close(terminal_outfp);
    exit(0);
  }
}

help(s)
  unsigned char  *s;
{
  int   i;

  sprintf(work,"%c[7m          MyCli Help          %c[0m\n", 0x1b, 0x1b);
  WriteWork();
  for (i=0; help_messages[i]; i++) {
    sprintf(work, "%s\n", help_messages[i]);
    WriteWork();
  }
  sprintf(work, "%c[7m          End of Help         %c[0m\n", 0x1b, 0x1b);
  WriteWork();
}

gfxoff()
{
  if (gfx_flag == 1)
    terminate();
  gfx_flag = 0;
}

speechon()
{
  oktosay = 1;
}

speechoff()
{
  oktosay = 0;
}

offline(s)
unsigned char  *s;
{
  modem_online = 0;
  say_string((char*)0, 1);
}

online(s)
  unsigned char  *s;
{
  modem_online = !0;      /* signal that modem is live !!! */
  if (initialize()) {     /* set baud rate, etc. */
    Write(terminal_outfp, WelcomeMessage, strlen(WelcomeMessage));
    while (modem_online) {
      bdoneflag = 0;    /* terminal mode on flag */
      Write(terminal_outfp, OnlineMessage, strlen(OnlineMessage));
      while (!bdoneflag) {
        check_keyboard();
        check_modem();
        if (bdoneflag || num_of_chars > MAX_CHARS || no_io > 0) {
          if (num_of_chars > 0) {
            Write(terminal_outfp, iobuf, num_of_chars);
            num_of_chars = 0;
          }
        }
      }
      Write(terminal_outfp, OfflineMessage, strlen(OfflineMessage));
      Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
      getcommand(buf);
      CommandInterpreter(buf);
    }
    cleanup();
  }
  modem_online = 0;
}

getcommand(s)
  unsigned char  *s;
{
  unsigned char  c;
  unsigned col;

  col = 0;
  while (1) {
    Read(terminal_infp, &c, 1);
    switch(c) {
      case 8:
        if (col) {
          c = 8;
          Write(terminal_outfp, &c, 1);
          c = ' ';
          Write(terminal_outfp, &c, 1);
          c = 8;
          Write(terminal_outfp, &c, 1);
          col--;
        }
        continue;
      case 10:
      case 13:
        sprintf(work, "\n");
        WriteWork();
        s[col++] = '\0';
        break;
      case 0x1b:
      case 24:
        while (col) {
          c = 8;
          Write(terminal_outfp, &c, 1);
          c = ' ';
          Write(terminal_outfp, &c, 1);
          c = 8;
          Write(terminal_outfp, &c, 1);
          col--;
        }
        continue;
      case 0x9b:
        if (process_event(&s[col])) {
          strcat(s, "\n");
          Write(terminal_outfp, &s[col], strlen(&s[col]));
          break;
        }
        continue;
      default:
        s[col++] = c;
        Write(terminal_outfp, &c, 1);
        continue;
    }
    break;
  }
}

/*
 * this function converts an incoming ANSI escape sequence
 * and processes it.  A buffer is passed where any function
 * key expansion is to take place. If the buffer is modified
 * for any reason, this function returns true.
 */
process_event(cmd_line)
  unsigned char  *cmd_line;
{
  int   i;
  unsigned char  c;
  char  event_buffer[32];

  i = 0;
  while (1) {
    Read(terminal_infp, &c, 1);
    event_buffer[i] = c;
    if (c == '~' || c == '|' || c == 'A' || c == 'B' || c == 'C' || c == 'D')
      break;
    i++;
  }
  event_buffer[i+1] = '\0';
  if (event_buffer[i] == '~') {
    if (event_buffer[0] == '?') {
      strcpy(cmd_line, "help");
      return !0;
    } else if (isdigit(event_buffer[0])) {
      if (function_key(atoi(event_buffer), cmd_line))
        return !0;
      else if (atoi(event_buffer) == 6)
        bdoneflag = !0;
    }
  } else if (i == 0 && (event_buffer[0] >= 'A' && event_buffer[0] <= 'D')) {
    cmd_line[0] = '\033';
    cmd_line[1] = event_buffer[0];
    cmd_line[2] = '\000';
    return !0;
  }
  return 0;
}

/*
 * if a definition for the function key fkey exists (0-19), then
 * the translation for the function key is copied to the string
 * s, and this function returns !0.  Otherwise, now translation
 * exists, and this function returns 0.
 */
function_key(fkey, s)
  int fkey;
  unsigned char  *s;
{
  int   i;

  if (function_key_definitions[fkey] != 0) {
    for (i=0; function_key_definitions[fkey][i] != '\0'; i++)
      s[i] = function_key_definitions[fkey][i];
    s[i] = '\0';
    return !0;
  }
  return 0;
}

initialize() {
  ModemReadRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemReadRequest),
                     MEMF_PUBLIC | MEMF_CLEAR);
  ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  ModemReadRequest->IOSer.io_Message.mn_ReplyPort =
                                           CreatePort("Read_RS",0);
  if (OpenDevice(SERIALNAME, NULL, ModemReadRequest, NULL)) {
    sprintf(work, "%c[36mCan't open serial read device%c[0m\n",
            0x1b, 0x1b);
    WriteWork();
    DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
    FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
    return 0;
  }
  ModemReadRequest->IOSer.io_Command = CMD_READ;
  ModemReadRequest->IOSer.io_Length = 1;
  ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];

  ModemWriteRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemWriteRequest),
                      MEMF_PUBLIC | MEMF_CLEAR);
  ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  ModemWriteRequest->IOSer.io_Message.mn_ReplyPort =
                                                 CreatePort("Write_RS",0);
  if (OpenDevice(SERIALNAME, NULL, ModemWriteRequest, NULL)) {
    sprintf(work, "%c[36mCan't open serial write device%c[0m\n",
            0x1b, 0x1b);
    WriteWork();
    DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
    FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
    DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
    FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
    return 0;
  }
  ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
  ModemWriteRequest->IOSer.io_Length = 1;
  ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];

  ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  ModemReadRequest->io_Baud = 1200;
  ModemReadRequest->io_ReadLen = 8;
  ModemReadRequest->io_WriteLen = 8;
  ModemReadRequest->io_CtlChar = 1L;
  ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  DoIO(ModemReadRequest);
  ModemReadRequest->IOSer.io_Command = CMD_READ;
  BeginIO(ModemReadRequest);
  return !0;
}

cleanup() {
  CloseDevice(ModemReadRequest);
  DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));

  CloseDevice(ModemWriteRequest);
  DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
  FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));

  Write(terminal_outfp, GoodbyeMessage, strlen(GoodbyeMessage));
}

check_keyboard()
{
  unsigned char  *pc;

  if (WaitForChar(terminal_infp, 1)) {
    Read(terminal_infp, &rs_out[0], 1);
    switch ((unsigned char)rs_out[0]) {
      case 0x9b:                          /* ANSI keyboard stuff */
        if (process_event(&buf[0])) {    /* send the translation */
          pc = &buf[0];
          while (*pc != '\0') {
            rs_out[0] = *pc++;
            if (TermEcho)
              Write(terminal_outfp, &rs_out[0], 1);
            DoIO(ModemWriteRequest);
            check_modem();
          }
        }
        break;
      case 0x05:                    /* toggle keystroke echo */
        TermEcho = !TermEcho;
        sprintf(work, "%c[36mEcho %s%c[0m\n", 0x1b, TermEcho?"ON":"OFF",
                0x1b);
        WriteWork();
        break;
      default:
        if (TermEcho)
          Write(terminal_outfp, &rs_out[0], 1);
        DoIO(ModemWriteRequest);
    }
  }
}

/*
 * Check to see if the Read Request IO has completed from the modem.
 */
check_modem()
{
  static int sayflag = 0;
  static char saystring[133];
  static int sayind = 0;
  static int escape_sequence = 0;

  if (CheckIO(ModemReadRequest)) {
    WaitIO(ModemReadRequest);
    rs_in[0] &= 0x7f;

    if (rs_in[0] == '\001' && oktosay == 1) {
      sayflag = 1;
      BeginIO(ModemReadRequest);
      return;
    }

    if (oktosay == 1 && sayflag) {
      if (rs_in[0] >= ' ' && rs_in[0] < (char)127) {
        saystring[sayind++] = rs_in[0];
      } else {
	Write(terminal_outfp, iobuf, num_of_chars);
	rs_out[0] = CTRLS;
	DoIO(ModemWriteRequest);
	num_of_chars = 0;
        saystring[sayind++] = (char)0;
        say_string(saystring,0);
        sayind = 0;
	sayflag = 0;
	rs_out[0] = CTRLQ;
	DoIO(ModemWriteRequest);
      }
    }
    if (rs_in[0] == '\033') {
      escape_sequence = 1;
    } else if (escape_sequence == 1) {
      if (rs_in[0] == 'G') {
        Graphics();
      } else {
        iobuf[num_of_chars++] = '\033';
        iobuf[num_of_chars++] = rs_in[0];
        no_io = 0;
      }
      escape_sequence = 0;
    } else {
      iobuf[num_of_chars++] = rs_in[0];
      no_io = 0;
    }
    BeginIO(ModemReadRequest);
  } else {
    no_io++;
  }
}

sendchar(ch)
  int ch;
{
  rs_out[0] = ch;
  DoIO(ModemWriteRequest);
}

readchar()
{
  unsigned char c;
  int rd,ch;
  rd = FALSE;
  while (rd == FALSE) {
    if(CheckIO(ModemReadRequest)) {
      WaitIO(ModemReadRequest);
      ch=rs_in[0];
      rd = TRUE;
      BeginIO(ModemReadRequest);
    }
  }
  if (rd == FALSE) {
    timeout = TRUE;
    emits("\nTimeout Waiting For Character\n");
  }
  c = ch;
  return(c);
}

rb(file)
  char *file;
{
  int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  unsigned int checksum, j, bufptr,i;
  char numb[10];
  bytes_xferred = 0L;
  i = 10;
  if ((fd = creat(file, 0)) < 0) {
    emits("Cannot Open File\n");
    return FALSE;
  } else
    emits("Receiving File\n");
  timeout=FALSE;
  sectnum = errors = bufptr = 0;
  sendchar(NAK);
  firstchar = 0;
  while (firstchar != EOT && errors != ERRORMAX) {
    errorflag = FALSE;
    do {
      firstchar = readchar();
      if (timeout == TRUE)
        return FALSE;
    }
    while (firstchar != SOH && firstchar != EOT);
    if (firstchar == SOH) {
      emits("Getting Block ");
      stci_d(numb,sectnum,i);
      emits(numb);
      emits("...");
      sectcurr = readchar();
      if (timeout == TRUE)
        return FALSE;
      sectcomp = readchar();
      if (timeout == TRUE)
        return FALSE;
      if ((sectcurr + sectcomp) == 255) {
        if (sectcurr == (sectnum + 1 & 0xff)) {
          checksum = 0;
          for (j = bufptr; j < (bufptr + SECSIZ); j++) {
            bufr[j] = readchar();
            if (timeout == TRUE)
              return FALSE;
            checksum = (checksum + bufr[j]) & 0xff;
          }
          if (checksum == readchar()) {
            errors = 0;
            sectnum++;
            bufptr += SECSIZ;
            bytes_xferred += SECSIZ;
            emits("verified\n");
            if (bufptr == BufSize) {
              bufptr = 0;
              if (write(fd, bufr, BufSize) == EOF) {
                emits("\nError Writing File\n");
                return FALSE;
              };
            };
            sendchar(ACK);
          } else {
            errorflag = TRUE;
            if (timeout == TRUE)
              return FALSE;
          }
        } else {
          if (sectcurr == (sectnum & 0xff)) {
            emits("\nReceived Duplicate Sector\n");
            sendchar(ACK);
          } else
            errorflag = TRUE;
        }
      } else
         errorflag = TRUE;
    }
    if (errorflag == TRUE) {
      errors++;
      emits("\nError\n");
      sendchar(NAK);
    }
  };
  if ((firstchar == EOT) && (errors < ERRORMAX)) {
    sendchar(ACK);
    write(fd, bufr, bufptr);
    write(fd, "\n", 1);
    close(fd);
    return TRUE;
  }
  return FALSE;
}

sb(file)
  char *file;
{
  int sectnum, bytes_to_send, size, attempts, c, i;
  unsigned checksum, j, bufptr;
  char numb[10];
  timeout=FALSE;
  bytes_xferred = 0;
  i = 10;
  if ((fd = open(file, 1)) < 0) {
    emits("Cannot Open Send File\n");
    return FALSE;
  } else
    emits("Sending File\n");
  attempts = 0;
  sectnum = 1;
  j=1;
  while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
  if (j >= (ERRORMAX)) {
    emits("\nReceiver not sending NAKs\n");
    return FALSE;
  };
  while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
  {
    if (bytes_to_send == EOF) {
      emits("\nError Reading File\n");
      return FALSE;
    };
    bufptr = 0;
    while (bytes_to_send > 0 && attempts != RETRYMAX) {
      attempts = 0;
      do {
        sendchar(SOH);
        sendchar(sectnum);
        sendchar(~sectnum);
        checksum = 0;
        size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
        bytes_to_send -= size;
        for (j = bufptr; j < (bufptr + SECSIZ); j++)
          if (j < (bufptr + size)) {
            sendchar(bufr[j]);
            checksum += bufr[j];
          } else {
            sendchar(0);
          }
        sendchar(checksum & 0xff);
        attempts++;
        c = readchar();
        if (timeout == TRUE)
          return FALSE;
      } while ((c != ACK) && (attempts != RETRYMAX));
      bufptr += size;
      bytes_xferred += size;
      emits("Block ");
      stci_d(numb,sectnum,i);
      emits(numb);
      emits(" sent\n");
      sectnum++;
    }
  }
  close(fd);
  if (attempts == RETRYMAX) {
    emits("\nNo Acknowledgment Of Sector, Aborting\n");
    return FALSE;
  } else {
    attempts = 0;
    do {
      sendchar(EOT);
      attempts++;
    } while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
    if (attempts == RETRYMAX)
      emits("\nNo Acknowledgment Of End Of File\n");
  };
  return TRUE;
}

emits(embuf)
  char *embuf;
{
  Write(terminal_outfp, embuf, strlen(embuf));
}

Graphics()
{
  char buf[82], *gr_buf;
  int gr_len, r, g, b, color, x1, y1, x2, y2;
  int polx[256], poly[256], n, clip, xmin, ymin, xmax, ymax;
  int i;

  if (gfx_flag == 0) {
    gfx_flag = 1;
    initialise();
  } else
    get_screen();
  rs_out[0] = CTRLS;
  DoIO(ModemWriteRequest);
  BeginIO(ModemReadRequest);
  for(;;) {
    gr_len = 0;
    buf[0] = (char)0;
    gr_buf = &(buf[1]);
    while(gr_buf[gr_len-1] != '\015') {
      if (CheckIO(ModemReadRequest)) {
        WaitIO(ModemReadRequest);
        rs_in[0] &= 0x7f;
        if (rs_in[0] != '\012') {
          gr_buf[gr_len++] = rs_in[0];
        }
        BeginIO(ModemReadRequest);
      } else {
        rs_out[0] = CTRLQ;
        DoIO(ModemWriteRequest);
      }
    }
    rs_out[0] = CTRLS;
    DoIO(ModemWriteRequest);
    gr_buf[gr_len-1] = (char)0;
    switch (gr_buf[0]) {
      case 'T':
/*        terminate(); */
        put_screen();
	rs_out[0] = CTRLQ;
	DoIO(ModemWriteRequest);
        return;
      case 'C':
        sscanf(&(gr_buf[1]), "%d%d%d%d", &color, &r, &g, &b);
        define_color(color, r, g, b);
        if (check_user_action() == -1) {
          put_screen();
          return;
        }
        break;
      case 'L':
        sscanf(&(gr_buf[1]), "%d%d%d%d%d", &x1, &y1, &x2, &y2, &color);
        draw(x1, y1, x2, y2, color);
        if (check_user_action() == -1) {
          put_screen();
          return;
        }
        break;
      case 'P':
        sscanf(&(gr_buf[1]), "%d%d%d%d%d%d%d", &n, &color, &clip,
					       &xmin, &ymin, &xmax, &ymax);
        for (i=0; i<n; i++) {
          gr_len = 0;
          buf[0] = (char)0;
          gr_buf = &(buf[1]);
          while(gr_buf[gr_len-1] != '\015') {
            if (CheckIO(ModemReadRequest)) {
              WaitIO(ModemReadRequest);
              rs_in[0] &= 0x7f;
              if (rs_in[0] != '\012') {
                gr_buf[gr_len++] = rs_in[0];
              }
              BeginIO(ModemReadRequest);
            } else {
	      rs_out[0] = CTRLQ;
	      DoIO(ModemWriteRequest);
	    }
          }
          gr_buf[gr_len-1] = (char)0;
	  sscanf(gr_buf,"%d%d", &(polx[i]), &(poly[i]));
        }
	rs_out[0] = CTRLS;
	DoIO(ModemWriteRequest);
/* 	poly_draw(polx, poly, n, color, clip, xmin, ymin, xmax, ymax); */
        if (check_user_action() == -1) {
          put_screen();
          return;
        }
	break;
    }
  }
}
