/*
 * MSDOSIO.C: terminal io for MS-DOS
 * C Durland	Public Domain
 */
/*
 * The functions in this file negotiate with the operating system for
 * characters, and write characters in a barely buffered fashion on the
 * display.
 */

#include <stdio.h>
#include <dos.h>
#include "ed.h"
#include "term.h"

#define MASK 0xFF	/* mask for ioctl set */
#define RAW 0x20	/* ioctl raw bit */
#define STDIN 0
#define STDOUT 1

/*
 * This function is called once to set up the terminal device streams.
 */
void ttopen()
{
  bdos(0x33,0,1);	/* turn off control C checking */
}

/*
 * This function gets called just before we go back home to the command
 *   interpreter.
 */
void t_close()
{
  bdos(0x33,1,1);	/* turn on control C checking */
}

/*
 * Write a character to the display.
 * Use the rawest console output routine that handles backspace, \r and \n.
 * On MS-DOS terminal I/O is unbuffered, so we just write the byte out.
 */
void t_putchar(c) unsigned char c;
{
  bdos(6,c,0);
}

/*
 * Flush terminal buffer.  Does real work where the terminal output is
 *   buffered up.  A no-operation on systems where byte-at-a-time terminal
 *   I/O is done.
 */
void t_flush() {}

/*
 * Read a character from the terminal, performing no editing and doing no
 *   echo at all.
 * Map terminal softkeys, etc to ME keys.  Do *NOT* map control keys.
 */
KeyCode t_getchar()
{
  unsigned char c;

  c = bdos(7,0,0);
  return (KeyCode)c;
}

/*
 * Check to see is a key is waiting.
 * Used to interrupt processing if input is pending or to detect if a soft
 *   key has been hit (the terminal sends multiple characters for each
 *   softkey).
 * Don't use function B because it checks for ^C.
 */
int keywaiting()
{
  union REGS in, out;

  in.h.ah = 0x44; in.h.al = 6; in.x.bx = STDIN;
  intdos(&in,&out);	/* get stdin info */
  return out.h.al;
}

static long int get_time(init)
{
  static int day;
  long int time = 0;
  union REGS r;

  r.h.ah = 0x2A; int86(0x21,&r,&r);		/* read day, month, year */
  if (init) day = r.h.al;			/* day of week */
  else if (r.h.al != day) time = 86400L;	/* day changed */
  r.h.ah = 0x2C; int86(0x21,&r,&r);		/* read hrs, mins, secs */
  time += r.h.ch*3600L +r.h.cl*60 +r.h.dh;   /* convert hhmmss to seconds */
  return time;
}

   /* Wait for a key to be pressed for no more than sec seconds.
    * Use 0 seconds to check to see if a key is in the input que.
    * Warning:  This rouine is only good for 32K seconds (about 9 hours).
    *   If sec is a long the limit is still 24 hours.
    */
wait_for_key(sec)
{
  long int times_up;

  if (sec == 0) return keywaiting();
  times_up = get_time(TRUE) +sec;
  do
  {
    if (keywaiting()) return TRUE;
  } while (get_time(FALSE) < times_up);
  return FALSE;
}
