/* Configurable Terminal Program, (c) 1981 by Joe Felsenstein */
/* OK to copy for nonprofit purposes */
/* This is the version preconfigured for the Osborne-1 */

#include   "B:BDSCIO.H"
#define    TRUE      1
#define    FALSE     0
#define    BUFRSIZE  32000
#define    CTRLD     4
#define    CTRLE     5
#define    CTRLF     6
#define    CTRLG     7
#define    LF        10
#define    CR        13
#define    CTRLR     18
#define    CTRLW     23
#define    CTRLZ     26

/* these following declarations declare the configuration parameters */
int halfduplex;

char cpch;   /* external storage location for CPM 2.x BDOS(6, ) calls */
char iobuf[BUFSIZ]; /* the IO buffer */
char filename[80];   /* room for a file name */
char buffer[BUFRSIZE];  /* the storage buffer */
int  stash, buflong, bsize;

modemrdy()
{
   int cx;

   cx = call(0x4000, 0, 0, 0, 0);
   if ((cx & 0x01) != 0)
      return(TRUE);
   else return(FALSE);
}

modemread()
{
   int x;

   x = bdos(3, 0);   /* Osborne modem port is CP/M Reader device */
   return (x);
}

keyrdy() 
{
   int x;

   cpch = bdos (6, 0xFF);
   if (cpch != 0)
      x = 1;
   else x = 0;
   return(x);
}

keyread()
{
   char ch;

   ch = cpch;         /* if keyrdy, char was stored in cpch */
   return(ch);
}

modemsend(ch)
char ch;
{
   int cx;

   cx = bdos(5, ch);   /* Osborne modem output is on CP/M list device */
   if (halfduplex) putch(ch);
}

buferrmsg()
{
   printf("%c%c%c%s", CTRLG, CTRLG, CTRLG, "BUFFER FULL! ");
   printf("%s\n", "BUFFER FILLING TURNED OFF!");
}

docommand(ch)
char ch;
{
   int i, gotcr, striplf;
   char c;

   switch (ch) {
      case CTRLD :
                   printf("%s", "Want to change <CR><LF> to <CR>? ");
                   printf("%s\n","(type Y or N)");
                   c = getchar();
                   printf("\n");
                   if ((c=='Y') | (c=='y'))
                      striplf = TRUE;
                   else striplf = FALSE;
                   gotcr = FALSE;
                   for (i = 1; i <= buflong; i++) {
                      c = buffer[i];
                      if ( (c == LF) && gotcr && striplf ) ;
                      else
                         modemsend (c);
                      if (!halfduplex) putch (c);
                      if (striplf) gotcr = (c == CR);
                      }
                   printf("%s\n", "------ FINISHED TRANSMITTING BUFFER -----");
                   break;
      case CTRLE : break;
      case CTRLF :
                   printf("%s", "name of file to read from your disk? ");
                   gets(filename);
                   i = fopen(filename, iobuf);
                   buflong = 0;
                   if (i == -1)
                      printf("%s %s\n", "Can't find file:", filename);
                   else {
                      i = c = getc(iobuf);
                      while ( (i != -1) && (c != CTRLZ) ) {
                         buffer[++buflong] = c;
                         putch(c);
                         i = c = getc(iobuf);
                         if (buflong == bsize) {
                            buferrmsg();
                            i = -1;
                            }
                         }
                      fclose (iobuf);
                      printf("%s\n", "------- FINISHED READING FILE --------");
                      }
                   break;
      case CTRLR :
                   stash = !stash;
                   if (stash) buflong = 0;
                   break;
      case CTRLW :
                   printf("%s ", "name of file to write on your disk:");
                   gets(filename);
                   i = fcreat(filename, iobuf);
                   if (i != -1) {
                      for (i = 1; i <= buflong; i++) {
                         putch(c = buffer[i]);
                         putc(c, iobuf);
                         }
                      putc(CTRLZ, iobuf);
                      fflush(iobuf);
                      fclose(iobuf);
                      printf("%s\n", "---------- FILE WRITTEN ------------");
                      }
                   else printf("%s %s\n", "ERROR IN CREATING FILE:", filename);
                   break;
      }
}

configure()
{
   char c;
   int i;

   printf("\n%s\n", "Want terminal to be half-duplex? (Y or N)");
   c = getchar();
   halfduplex = (toupper(c)  == 'Y');
   c = call(0x1F70, 0, 0, 0, 0);   /* move modem ready routine */
   poke (0x0003, (peek(0x0003) & 0xF3) | 0x04); /* set IOBYTE */ 
}

main ()
{   
   char ch, kch;
   int x, i;

   printf("%s\n", "Configurable Terminal Program, v2.0");
   printf("%s\n", "(c) 1981 by Joe Felsenstein");
   printf("%s\n\n", "OK to copy for nonprofit purposes");
   configure();
   printf("\n%s\n", "Commands: (^ indicates these are control characters)");
   printf("%s\n", "    ^D    Dump contents of buffer to modem");
   printf("%s\n", "    ^E    Exit to CP/M");
   printf("%s\n", "    ^F    Fill buffer from CP/M file (asks for name)");
   printf("%s\n", "    ^R    toggles filling of buffer from modem port");
   printf("%s\n", "    ^W    Writes buffer to CP/M file (asks for name)");
   printf("%s\n", "Now you are a terminal (control-E to stop being one)...");
   stash = FALSE;
   buflong = 0;
   bsize = BUFRSIZE;
   do {
      if (modemrdy()) {
         ch = modemread();
         if (stash) {
            if (buflong == bsize) {
               buferrmsg();
               stash = !stash;
               }
            else
               buffer[++buflong] = ch;
            }
         putch(ch & 0177);
         }
      if (keyrdy()) {
         kch = keyread() & 0177;  /* automatically strip parity bit */
         switch (kch) {
            case CTRLD :
            case CTRLE :
            case CTRLF :
            case CTRLR :
            case CTRLW :
               docommand(kch);
               break;
            default :
               modemsend(kch);
               break;
            }
         }
      }
   while ( kch != CTRLE);
   exit();
}
