/* pc.c - terminal I/O calls for GNU info for OS/2
   and other PC support functions
   Kai Uwe Rommel, 1990-1993
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/kbdscan.h>

#ifndef __RSXNT__
#define INCL_VIO
#include <os2emx.h>
static VIOCURSORINFO vci;
#endif

#include "pc.h"

#ifdef __RSXNT__

char buffer[4096];
int idx;

static void pc_flush(void)
{
  if (idx > 0)
    _rsxnt_write_with_ansi (buffer, idx);

  idx = 0;
}

void pc_putc (int c)
{
  if (idx == sizeof(buffer))
    pc_flush();

  buffer[idx++] = (char) c;
}

void pc_puts (char *s)
{
  while (*s)
    pc_putc(*s++);
}

void pc_putx (char *s, int x)
{
  for (; x; x--)
    pc_putc(*s++);
}

#endif

void pc_init (void)
{
#ifdef __RSXNT__
  extern void (*terminal_put_text_hook)();
  extern void (*terminal_write_chars_hook)();
  terminal_put_text_hook = pc_puts;
  terminal_write_chars_hook = pc_putx;
#else
  VIOCURSORINFO vcin;
  VioGetCurType(&vci, 0);
  vcin = vci;
  vcin.yStart = 0;
  vcin.cEnd = -100;
  VioSetCurType(&vcin, 0);
#endif
}

void pc_exit (void)
{
#ifndef __RSXNT__
  VioSetCurType(&vci, 0);
#endif
}

int pc_getc (int wait)
{
  int c;
  static int next;

  if (next)
    return c = next, next = 0, c;

#ifdef __RSXNT__
  if (wait)
    pc_flush();
#endif

  if ((c = _read_kbd (0, wait, 0)) == -1)
    return -1;

  if (c == 26)
    return next = 'V', 27;
  if (c != 0x00 && c != 0xE0)
    return c;

  if ((c = _read_kbd (0, wait, 0)) == -1)
    return -1;

  switch (c)
  {
  case K_F1:
    return 'H' - 64;

  case K_HOME:
    return 'A' - 64;
  case K_END:
    return 'E' - 64;

  case K_CTRL_HOME:
    return next = '<', 27;
  case K_CTRL_END:
    return next = '>', 27;

  case K_RIGHT:
    return 'F' - 64;
  case K_LEFT:
    return 'B' - 64;
  case K_DOWN:
    return 'N' - 64;
  case K_UP:
    return 'P' - 64;
  case K_INS:       /* jsawa */
    return 0;     /* How can we toggle insert mode ??? */
  case K_CTRL_LEFT:
    return next = 'B', 27;
  case K_CTRL_RIGHT:
    return next = 'F', 27;
#ifdef __EMX__
  case K_ALT_0:                /* for M+'0' :  */
    return next = '0', 27;
  case K_ALT_1:                /* for M+'1' :  */
    return next = '1', 27;
  case K_ALT_2:                /* for M+'2' :  */
    return next = '2', 27;
  case K_ALT_3:                /* for M+'3' :  */
    return next = '3', 27;
  case K_ALT_4:                /* for M+'4' :  */
    return next = '4', 27;
  case K_ALT_5:                /* for M+'5' :  */
    return next = '5', 27;
  case K_ALT_6:                /* for M+'6' :  */
    return next = '6', 27;
  case K_ALT_7:                /* for M+'7' :  */
    return next = '7', 27;
  case K_ALT_8:                /* for M+'8' :  */
    return next = '8', 27;
  case K_ALT_9:                /* for M+'9' :  */
    return next = '9', 27;
  case K_ALT_A:
    return next = 'A', 27;
  case K_ALT_B:
    return next = 'B', 27;
  case K_ALT_C:
    return next = 'C', 27;
  case K_ALT_D:
    return next = 'D', 27;
  case K_ALT_E:
    return next = 'E', 27;
  case K_ALT_F:
    return next = 'F', 27;
  case K_ALT_G:
    return next = 'G', 27;
  case K_ALT_H:
    return next = 'H', 27;
  case K_ALT_I:
    return next = 'I', 27;
  case K_ALT_J:
    return next = 'J', 27;
  case K_ALT_K:
    return next = 'K', 27;
  case K_ALT_L:
    return next = 'L', 27;
  case K_ALT_M:
    return next = 'M', 27;
  case K_ALT_N:
    return next = 'N', 27;
  case K_ALT_O:
    return next = 'O', 27;
  case K_ALT_P:
    return next = 'P', 27;
  case K_ALT_Q:
    return next = 'Q', 27;
  case K_ALT_R:
    return next = 'R', 27;
  case K_ALT_S:
    return next = 'S', 27;
  case K_ALT_T:
    return next = 'T', 27;
  case K_ALT_U:
    return next = 'U', 27;
  case K_ALT_V:
    return next = 'V', 27;
  case K_ALT_W:
    return next = 'W', 27;
  case K_ALT_X:
    return next = 'X', 27;
  case K_ALT_Y:
    return next = 'Y', 27;
  case K_ALT_Z:
    return next = 'Z', 27;
  case K_ALT_DEL:              /* for M+'DEL' : scroll-other-window-backward */
    return next = '\177', 27;
  case K_ALT_PERIOD:           /* for M+'<' beginning-of-node */
    return next = '<', 27;
  case K_ALT_COMMA:            /* for M+'>' end-of-node */
    return next = '>', 27;
  case K_ALT_PAD_MINUS:        /* for M+'-' add-digit-to-numeric-arg */
    return next = '-', 27;
#endif
  case K_DEL:
    return 'D' - 64;
  case K_PAGEUP:
    return next = 'V', 27;
  case K_PAGEDOWN:
    return 'V' - 64;
  default:
    return ' ';
  }
}
