/**********************************************************************/
/*            Low-Level I/O Routines with Carrier Detect              */
/*                                                                    */
/* By: Bryan D. Hall                                   Date: 03/15/89 */
/* GEnie Address: BDHALL                                              */
/* Fnet  Address: Bryan Hall, Node 227 CO (719)543-1869 12/24/96 HST  */
/*                                        M-F 4PM-10AM, 24Hrs Weekends*/
/*                                                                    */
/**********************************************************************/


/** cd_check() ********************************************************/
/*   INPUT: None (hardware) CD Line                                   */
/* PROCESS: This is a routine to check for carrier. Exits program if  */
/*          no carrier                                                */
/*  OUTPUT: None.  Exits with status 1                                */
/**********************************************************************/

void cd_check()
{
char *gpip;
long stack;
char test;

   gpip=(char *)0xFFFFFA01L;
   stack=Super(0L);
   test= *gpip;    
   Super(stack);
   if (test & 2) 
      exit(1); /* no carrier.. get out of this! */
}



/** cd_bconin(int) ****************************************************/
/*   INPUT: Device number. 0=prn:, 1=aux:, 2=con:, or 3=MIDI.  See    */
/*          Bconin for more info.                                     */
/* PROCESS: Same as for Bconin, but also checks for a carrier.        */
/*  OUTPUT: See Bconin                                                */
/**********************************************************************/

long cd_bconin(device)
int device;
{
long temp;

     switch(device)
          {
          case 1:   /* AUX: set as primary device */
                    cd_check();    /* first make sure there is a carrier */

                    temp = Bconstat(2); /* check console */

                    if (temp == -1)
                         return(Bconin(2));  /* then get char from console */
                    else
                         return(Bconin(device));  /* then get char from device */
                    break;

          case 2:   /* CON: set as primary device */
                    return(Bconin(device));  /* then get char from console */
                    break;

          case 3:   /* MIDI: set as primary device */
                    temp = Bconstat(2); /* check console */

                    if (temp == -1)
                         return(Bconin(2));  /* then get char from console */
                    else
                         return(Bconin(device));  /* then get char from device */
                    break;
          }
}



/** cd_bconout(int,int) ***********************************************/
/*   INPUT: (1) Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. see*/
/*          Bconout for more info.                                    */
/*          (2) Character to output, in low byte.                     */
/* PROCESS: Same as for Bconout, except checks for a carrier, and also*/
/*          sends the character to the keyboard if aux: is selected.  */
/*  OUTPUT: None                                                      */
/**********************************************************************/

void cd_bconout(device,character)
int device, character;
{

     switch(device)
          {
          case 1:   /* aux: set as the primary device */
                    cd_check();    /* first make sure there is a carrier */
     
                    Bconout(device,character); /* sent to device and console */
                    Bconout(2,character);
                    break;

          case 0:   /* Any other legal device */
          case 2:
          case 3:
          case 4:
          case 5:
                    Bconout(device,character); /* send to device only */
                    break;

          }
}
     

/** cd_bconstat(int) **************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, or 3=MIDI.  See     */
/*          Bconstat for more info.                                   */
/* PROCESS: Same as for Bconstat, except checks for a carrier, and    */
/*          also checks the keyboard if aux: is selected.             */
/*  OUTPUT: Returns -1 if at least one character is ready, else 0     */
/**********************************************************************/

long cd_bconstat(device)
int device;
{
long temp;

     switch(device)
          {
          case 1:   /* AUX: set as primary device */
                    cd_check();    /* first make sure there is a carrier */

                    temp = Bconstat(2); /* check console */

                    if (temp == -1)
                         return(temp);  /* then send "console is ready" */
                    else
                         return(Bconstat(device)); /* otherwise check AUX: */
                    break;

          case 0:   /* PRN:, CON:, or MIDI: */
          case 2:
          case 3:
                    return(Bconstat(device));
                    break;
          }
}



/** cd_bcostat(int) ***************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc.  See   */
/*          Bcostat for more info.                                    */
/* PROCESS: Same as for Bcostat, except it also checks for a carrier. */
/*  OUTPUT: Returns -1 if device is ready, else 0.                    */
/**********************************************************************/

long cd_bcostat(device)
int device;
{
     switch(device)
          {
          case 1:   /* AUX: set as primary device */
                    cd_check();    /* first make sure there is a carrier */
                    return(Bcostat(device));
                    break;

          case 0:   /* Any other legal device */
          case 2:
          case 3:
          case 4:
          case 5:
                    return(Bcostat(device));
                    break;
          }
}


/** cd_getchar(int) ***************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, or 3=MIDI.  See     */
/*          Bcostat for more info                                     */
/* PROCESS: Waits for a character from the specified device.  Then it */
/*          checks to see if the chatacter is printable.  If so, it   */
/*          is displayed and returned.  However, if the character is  */
/*          a <CTRL-S>, the routine remembers this, and the next time */
/*          called, will not echo the character, but will return it   */
/*          and cancel the pause.                                     */
/*          NOTE: If the device is not con:, it will also get the     */
/*                from the keyboard.                                  */
/*  OUTPUT: Returns the character, as an int.                         */
/**********************************************************************/

int cd_getchar(device)
int device;
{
long temp;
static int paused;

     while (cd_bconstat(device) == 0)   /* wait for a character */
          ;

     temp = cd_bconin(device);     /* get character */

     if ((isprint((int)temp) || ((int)temp == 10) || ((int)temp == 13)
          || ((int)temp == 8)) && !paused )
          {
          cd_bconout(device,(int)temp);    /* echo out to device */
          }
     else
          {
          if ((int)temp == 19)  /* CTRL-S */
               paused = 1;  /* set flag */
          else
               paused = 0; /* not paused */
          }


     return( (int)temp );     /* return ASCII code */
}


/** cd_hgetchar(int) **************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, or 3=MIDI.  See     */
/*          Bcostat for more info.                                    */
/* PROCESS: Waits for a character from the specified device.  Does NOT*/
/*          echo character to device or screen.                       */
/*  OUTPUT: Returns the character as an int.                          */
/**********************************************************************/

int cd_hgetchar(device) /* hidden get character (no echo) */
int device;
{
long temp;

     while (cd_bconstat(device) == 0)   /* wait for a character */
          ;

     temp = cd_bconin(device);     /* get character */

     return( (int)temp );     /* return ASCII code */
}


/** cd_putchar(char,int) **********************************************/
/*   INPUT: (1) Character to output.                                  */
/*          (2) Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. See*/
/*          Bcostat for more info.                                    */
/* PROCESS: Sends out a character to the specified device.  If the    */
/*          character is a LineFeed, then it also sends a <CR>.       */
/*          NOTE: If the device is not con:, it will also send the    */
/*                char. to the screen.                                */
/*  OUTPUT: None                                                      */
/**********************************************************************/

void cd_putchar(inchar, device)
char inchar;
int device;
{
     cd_bconout(device, (int)inchar);   /* send out character */

     if (inchar == 10)    /* LF */
          cd_bconout(device, 13);   /* send out CR */

}


/** cd_gets(char,int,int) *********************************************/
/*   INPUT: (1) "String" pointer.                                     */
/*          (2) Maximum number of chars to get.                       */
/*          (3) Device number 0=prn:, 1=aux:, 2=con:, or 3=MIDI.  See */
/*          Bcostat for more info.                                    */
/* PROCESS: Works somewhat like gets(), except that you can set the   */
/*          maximum number of characters to be typed in, plus allows  */
/*          for non-redirectable input.  It also sends out a <BELL>   */
/*          character when a user tries to backspace past the         */
/*          beginning of the line, and also after the last acceptable */
/*          character space has been filled.  This allows the user to */
/*          then backspace for corrections.                           */
/*          NOTE: If the device is not con:, it will also get the     */
/*                "string" from the keyboard.                         */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void cd_gets(s,n,device)
char s[];
int n,device;
{
register int c;
int at_now=0;
long temp;

    while(1)
          {

          while (cd_bconstat(device) == 0)   /* wait for a character */
               ;

          temp = cd_bconin(device);     /* get character */

          c = (int)temp;

          if (c == 8) /* BS */
               {
               if (at_now > 0)
                    {
                    n+=1;
                    at_now-=1;
                    
                    cd_bconout(device,c);    /* echo out to device */
                    }
               else
                    {
                    cd_bconout(device,7); /* echo bell out to device */
                    }                    
               }
          else
               {
               if ((isprint(c) || (c == 10) || (c == 13)
                      || (c == 8)))
                    {
                    s[at_now++] = c;

                    if (!(n-2))
                         {
                         cd_bconout(device,7); /* echo bell out to device */
                         }     
                    
                    if ((--n <= 0) || (c == 13) || (s[at_now-1] == '\n'))
                         {
                         s[at_now-1] = '\0';
                         return;
                         }

                    cd_bconout(device,c);    /* echo out to device */

                    }
               }
          }
}



/** cd_puts(char,int) *************************************************/
/*   INPUT: (1) Pointer to "string" to output.                        */
/*          (2) Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. See*/
/*          Bcostat for more info.                                    */
/* PROCESS: Works just like puts() (except for re-direction           */
/*          protection), plus adds the pause features found in the    */
/*          cd_putchar routine.                                       */
/*          NOTE: If the device is not con:, it will also send the    */
/*                "string" to the screen.                             */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void cd_puts(s,device)
char *s;
int device;
{
int c;

     while (c = *s++)
          cd_putchar(c, device);
}


/** cd_nputs(char,int,int) ********************************************/
/*   INPUT: (1) Pointer to "string" to be output.                     */
/*          (2) Maximum number of chars to output.                    */
/*          (3) Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. See*/
/*          Bcostat for more info                                     */
/* PROCESS: Works just like cd_puts() but allows you to specify the   */
/*          maximum number of characters to be output.                */
/*          NOTE: If the device is not con:, it will also send the    */
/*                "string" to the screen.                             */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void cd_nputs(s,n,device)
char *s;
int device,n;
{
int c;

     while ((c = *s++) && (--n))
          cd_putchar(c, device);
}


/** clr_scrn(int) *****************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. see    */
/*          Bcostat for more info                                     */
/* PROCESS: Sends both a VT-52 clear screen & home cursor, and a <LF> */
/*          to the device, and just the VT-52 code to con:            */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void clr_scrn(device)
int device;
{
     cd_puts("\033E \f",device); /* clear screen */
     cd_puts("\033E",2);
}


/** read_file(char,int) ***********************************************/
/*   INPUT: (1) Pointer to file path\name. Exp: "c:\txt\read.me"      */ 
/*          (2) Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc. See*/
/*          Bcostat for more info                                     */
/* PROCESS: Opens an ASCII (non-binary) file in read-only mode and    */
/*          sends it one character at a time, to the device.  If a    */
/*          <CTRL-S> is recieved (not echoed to device), it will pause*/
/*          until any other character is received.  If <CTRL-C> is    */
/*          recieved when not paused, it will close the file and      */
/*          abort.  If the file cannot be opened, a message will be   */
/*          displayed and the function will abort.                    */
/*          NOTE: If the device is not con:, it will also send the    */
/*                file to the screen.                                 */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void read_file(filename,device)
char filename[];
int device;
{
FILE *fp;
int ch, stat;
long temp=0L;

     if ((fp = fopen(filename,"r")) != NULL)
          {
          while (((ch = fgetc(fp)) != EOF) && (stat != 1))
               {
               cd_putchar(ch,device); /* send out char */

               if (cd_bconstat(device) == -1L) /* If true, char is availible*/
                    {
                    ch=cd_hgetchar(device);       /* Get input */

                    if (ch == 19) /* CTRL - S */
                         {
                         cd_hgetchar(device); /* wait for key */

                         stat = 0;
                         }
                    else if (ch == 3) /* CTRL - C */
                         stat = 1;
                    }
               }
          }
     else
          {
          cd_puts("\nCannot open file: ", device);
          cd_puts(filename, device);
          return;
          }

     fclose(fp);
}



/** do_pushany(int) ***************************************************/
/*   INPUT: Device number 0=prn:, 1=aux:, 2=con:, 3=MIDI, etc.  See   */
/*          Bcostat for more info.                                    */
/* PROCESS: Sends out a "Press any key message", then waits for a     */
/*          character.                                                */
/*          NOTE: If the device is not con:, it will also send the    */
/*                message to the screen.                              */
/*  OUTPUT: None.                                                     */
/**********************************************************************/

void do_pushany(device)
int device;
{

     cd_puts("\n\t\t\t << Press ANY Key to Continue >>\n",device);

     cd_hgetchar(device);
}

