/*
 * OS2IO.C: Terminal IO for OS/2
 * J Burnell	3/92	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>
#define INCL_BASE
#define INCL_NOPM
#define INCL_VIO
#define INCL_KBD
#include <os2.h>
#include <time.h>
#include "ed.h"
#include "term.h"

#include "me2.h"
#include "config.h"


#define MAXCOLS 120

KBDINFO	initialKbdInfo;	/* keyboard info		*/
void t_eeol ();

/*
 * This function is called once to set up the terminal device streams.
 */
void ttopen()
{
   PFNSIGHANDLER oldhandler;
   USHORT oldact;
   KBDINFO kbdInfo;

  /* turn off control C checking */
   DosSetSigHandler((PFNSIGHANDLER) NULL, &oldhandler, &oldact,
	                 SIGA_IGNORE, SIG_CTRLBREAK);
   DosSetSigHandler((PFNSIGHANDLER) NULL, &oldhandler, &oldact,
	                 SIGA_IGNORE, SIG_CTRLC);

  /* set up the keyboard */

    initialKbdInfo.cb = sizeof(initialKbdInfo);
    KbdGetStatus(&initialKbdInfo, 0);	
    kbdInfo = initialKbdInfo;
    kbdInfo.fsMask &= ~0x0001;		/* not echo on		*/
    kbdInfo.fsMask |= 0x0002;		/* echo off		*/
    kbdInfo.fsMask &= ~0x0008;		/* cooked mode off	*/
    kbdInfo.fsMask |= 0x0004;		/* raw mode		*/
    kbdInfo.fsMask &= ~0x0100;		/* shift report	off	*/
    KbdSetStatus(&kbdInfo, 0);

}

/*
 * This function gets called just before we go back home to the command
 *   interpreter.
 */
void t_close()
{
  /* close the keyboard */
  KbdSetStatus(&initialKbdInfo, 0); /* restore original state	*/
}

/*
 * 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;
{
  VioWrtTTY ((PCH)&c, 1, 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()
{

   KeyCode keycode;
   KBDKEYINFO keyInfo;

   KbdCharIn(&keyInfo, IO_WAIT, 0);	/* get a character	*/

   if (keyInfo.chChar == 0 || (keyInfo.chChar == 0xE0 && keyInfo.chChar != 0))
	{ if (map_key(keyInfo.chScan | (keyInfo.chChar << 8),&keycode))
	  return keycode; }
    else return (KeyCode)keyInfo.chChar;
}

/*
 * 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()
{
  return kbhit();
}

static long int get_time(init)
{
  time_t t;
  t = time (0);
  return t;
}

   /* 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;
}

#if FASTVIDEO
  /* Things to note about FastVideo:
   *   putline() will do all of the writing to the text area (except for
   *     help messages).
   *   t_eeol() will only be called for the message line or for help
   *     messages.
   *   t_eeop() need only clear the message line.  It should use t_eeol() to
   *     do this.
   *   t_putchar() will only write to the message line, help messages or
   *     (puts "message").
   * So, this means that the message line is really seprate from the text
   *   areas and t_putchar() and t_eeol() should use the same color (others
   *   will use tcolor and mcolor).  Default for the message line would be
   *   tcolor.  Help and (puts ...)  messages will be written in message
   *   color (which is (I hope) reasonable).
   * PC note:  Due to the way the BIOS is done, it is easier to have
   *   t_putchar() and t_eeol() use the BIOS character attribute as the
   *   color.
   */

int t_nrow = 24, t_ncol = 0;

int tcolor = 7, mcolor = 96;	/* text, modeline color defaults */
int zcolor = 7;

 /*
  * Called to set up the terminal.  Also called after a spawn.
  */
void t_open()
{
  VIOCURSORINFO cursorInfo, OldcursorInfo;

  ttopen();
  if (t_ncol == 0) fv_init();		/* only call fv_init() once */
/* set the cursor to a block */

  VioGetCurType (&OldcursorInfo, 0);
  cursorInfo.yStart = 1;
  cursorInfo.cEnd = 15;
  cursorInfo.cx = 1;
  cursorInfo.attr = 1;
  if (VioSetCurType (&cursorInfo, 0))
    VioSetCurType (&OldcursorInfo, 0);   /* reset to previous value */
}

int fv_init () {
  VIOMODEINFO vioModeInfo;
  vioModeInfo.cb = sizeof(vioModeInfo);
  VioGetMode (&vioModeInfo, 0);
  t_ncol = vioModeInfo.col;
  t_nrow = vioModeInfo.row - 1;   /* leave room for the message line */
}

void putline(row, buf, attr)	/* note: row is 0 relative */
  int row,attr; char *buf;
{
  VioWrtCharStrAtt ((PCH) buf, t_ncol, row, 0, (PBYTE) &attr, 0);
}

 /* Erase to end of page or screen.
  * For fast video, each line of the screen (except for the message line)
  *   will be completely filled by putline() so all this routine needs to
  *   clear is the message (last) line of the screen.
  */
void t_eeop() { movecursor(t_nrow,0,TRUE); t_eeol(); }

  /* Ring the bell.  beeper controls the volume:  0 (don't beep), n (some
   *   volume value).
   */
void t_beep()
{
  extern int beeper;

  if (beeper)
    DosBeep(1200, 175);
}

void t_move(row,col) int row, col;	/* move cursor to (row,col) */
{
  VioSetCurPos(row, col, 0);
}


char LineOfSpaces [MAXCOLS];

void t_eeol()		/* erase from cursor to end of line */
{
  register int n;
  USHORT CurCol, CurRow;

  /* find the current cursor position */
  VioGetCurPos ((PUSHORT) &CurRow, (PUSHORT) &CurCol, 0);
  n = t_ncol - CurCol;

  memset (LineOfSpaces, ' ', n);

  VioWrtCharStrAtt ((PCH) &LineOfSpaces [0], t_ncol - CurCol, CurRow, CurCol,
                    (PBYTE) &zcolor, 0);
}

#endif	/* FASTVIDEO */
