/* console.c: Console keyboard and vdu library               */
/* Copyright (C) J.G.Harston, 1997-2003                      */
/* version 0.10                                              */

#ifdef __win32__
#define CONKBD_PC
#define CONVDU_PC
#include <windows.h>
#include <wincon.h>
#include <conio.c>
#include <io.h>
#endif

#ifdef __dos__
#define CONKBD_PC
#define CONVDU_PC
#endif

int vduqlen=0;
char lastchar=0;
char vduq[10];

void con_init()
{
}


void con_wrch(int c)			/* Write a character to output	*/
{
if (isatty(fileno(stdout)) == 0) { putchar(c); return; }
if (vduqlen) {
  vduq[vduqlen--]=c;
  if (vduqlen != 0) return;
  switch(vduq[0]) {
    case 22: clrscr(); break;			/* MODE		*/
    case 31: gotoxy(vduq[2]+1,vduq[1]+1); break; /* TAB()	*/
    }
  return;
  }
switch (c) {
  case 127: putchar(8); putchar(32); putchar(8); break;
  case 9:   putchar(32); break;
  case 11:  gotoxy(wherex(),wherey()-1); break;	/* Move upwards	*/
  case 12:  clrscr(); break;			/* CLS		*/
  case 22:  vduq[0]=c; vduqlen=1; break;	/* MODE		*/
  case 30:  gotoxy(1,1); break;			/* HOME		*/
  case 31:  vduq[0]=c; vduqlen=2; break;	/* TAB()	*/
  default:  putchar(c);
  }
}


int con_readln(char *addr, int max, int lo, int hi) /* Read a line of input */
{
int c,l;

l=0; c=0;
for (;;) {
  c=con_rdch();
  if (c > 31 && c != 127 && c < 0x100 && l < max) {
    mem[addr++]=c;
    con_wrch(c);
    l++;
    }
  if ((c == 127 || c == 8 || c == 0x1c7 || c == 21) && l != 0) {
    for (;l > 0;) {
      addr--; l--;
      con_wrch(127);
      if (c != 21) break;
      }				/* NB: WinConsole doesn't wrap past col 0 */
    }
  if (c == 27 || c == 13 || c == 10) break;
  }
mem[addr]=0;
if (c == 27) return (-1);
con_wrch(10); con_wrch(13);
return(l);
}

#ifdef CONKBD_PC
unsigned char winkey[]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 00-07 */
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0xf0,0xd1, /* 08-0D,aBS,sTab */
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, /* 10-17 */
0x18,0x19,0x1a,0x1b,0xd5,0x1d,0x1e,0x1f, /* 18-1B,aEnter,1D-1F */
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, /* 20-27 */
0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, /* 28-2F */
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, /* 30-37 */
0x38,0x39,0x3a,0x81,0x82,0x83,0x84,0x85, /* 38-3A,F1-F5 */
0x86,0x87,0x88,0x89,0x8a,0x45,0x46,0xc8, /* F6-F10,45,46,Home */
0xcf,0xcb,0x4a,0xcc,0x4c,0xcd,0x4e,0xc9, /* Up,PgUp,4A,<-,4C,->,4E,End */
0xce,0xca,0xc6,0xc7,0x91,0x92,0x93,0x94, /* Down,PgDn,Ins,Del,sF1-sF4 */
0x95,0x96,0x97,0x98,0x99,0x9a,0xa1,0xa2, /* sF5-sF10,cF1,cF2 */
0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa, /* cF3-cF10 */
0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8, /* aF1-aF8 */
0xb9,0xba,0xa0,0xec,0xed,0xe9,0xea,0xe8, /* aF9-aF10,cPrint,c<-,c->,cEnd,cPgDn,cHome */
0xeb,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, /* cPgUp,79-7F */
0x80,0x81,0x82,0x83,0xeb,0x8b,0x8c,0x9b, /* 80-83,cPgUp,F11-12,sF11 */
0x9c,0xab,0xac,0xbb,0xbc,0xef,0x8e,0x8f, /* sF12,cF11-12,aF11-12,cUp,8E-8F */
0x90,0xee,0xe6,0xe7,0xe1,0x95,0x96,0xf8, /* 90,cDown,cIns,cDel,cTab,95,96,aHome */
0xff,0xfb,0x9a,0xfc,0x9c,0xfd,0x9e,0xf9, /* aUp,aPgUp,9A,a<-,9C,a->,9E,aEnd */
0xfe,0xfa,0xf6,0xf7,0xa4,0xf1,0xa6,0xa7, /* aDn,aPgDn,aIns,aDel,A4,aTab,A6-A7 */
0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, /* A8-AF */
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,
0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff };
#endif


int con_rdch()				/* Read a byte from input stream */
{
#ifndef CONKBD_PC
  return(getchar());
#endif
#ifdef CONKBD_PC
int c;

if (isatty(fileno(stdin)) == 0) if( (c=getchar()) != EOF) return(c);
c=_getch();				/* Read from console		*/
if (c != 0 && c != 0xe0) return(c);	/* Standard keyboard chars	*/
c=(char)GetAsyncKeyState(VK_SHIFT);
c=(char)GetAsyncKeyState(VK_CONTROL);
c=_getch();
if (c == 0x86) {			/* Either F12 or cPgUp		*/
  if (GetAsyncKeyState(VK_CONTROL)) c=0x78;  /* Remap cPgUp		*/
  }
if((c=winkey[c] | 0x100) < 0x1c0) return(c); /* Translate fn keys	*/
if(GetAsyncKeyState(VK_SHIFT))  return(c | 0x10);
return(c);
#endif
}


#ifdef CONKBD_PC
unsigned char winmap[]={
VK_SHIFT,	/* -001  Shift        */
VK_CONTROL,	/* -002  Ctrl         */
VK_MENU,	/* -003  Alt          */
VK_LSHIFT,	/* -004  Left Shift   */
VK_LCONTROL,	/* -005  Left Ctrl    */
VK_LMENU,	/* -006  Left Alt     */
VK_RSHIFT,	/* -007  Right Shift  */
VK_RCONTROL,	/* -008  Right Ctrl   */
VK_RMENU,	/* -009  Right Alt    */
VK_LBUTTON,	/* -010  Mouse Select */
VK_RBUTTON,	/* -011  Mouse Menu   */
VK_MBUTTON,	/* -012  Mouse Adjust */
0,		/* -013               */
0,		/* -014               */
0,		/* -015               */
0,		/* -016               */
'Q',		/* -017  Q            */
'3',		/* -018  3            */
'4',		/* -019  4            */
'5',		/* -020  5            */
VK_F4,		/* -021  F4           */
'8',		/* -022  8            */
VK_F7,		/* -023  F7           */
0xbd,		/* -024  -            */
'6',		/* -025  6            */
VK_LEFT,	/* -026  Left         */
VK_NUMPAD6,	/* -027  Keypad 6     */
VK_NUMPAD7,	/* -028  Keypad 7     */
VK_F11,		/* -029  F11          */
VK_F12,		/* -030  F12          */
VK_F10,		/* -031  F10          */
VK_SCROLL,	/* -032  Scroll Lock  */
VK_SNAPSHOT,	/* -033  Print        */
'W',		/* -034  W            */
'E',		/* -035  E            */
'T',		/* -036  T            */
'7',		/* -037  7            */
'I',		/* -038  I            */
'9',		/* -039  9            */
'0',		/* -040  0            */
0xbd,		/* -041  _            */
VK_DOWN,	/* -042  Down         */
VK_NUMPAD8,	/* -043  Keypad 8     */
VK_NUMPAD9,	/* -044  Keypad 9     */
VK_PAUSE,	/* -045  Break        */
0xdf,		/* -046  `/¦/¬        */
'3',		/* -047  £            */
VK_BACK,	/* -048  Backspace    */
'1',		/* -049  1            */
'2',		/* -050  2            */
'D',		/* -051  D            */
'R',		/* -052  R            */
'6',		/* -053  6            */
'U',		/* -054  U            */
'O',		/* -055  O            */
'P',		/* -056  P            */
0xdb,		/* -057  [            */
VK_UP,		/* -058  Up           */
VK_ADD,		/* -059  Keypad +     */
VK_SUBTRACT,	/* -060  Keypad -     */
VK_RETURN,	/* -061  Keypad Enter - same as Return */
VK_INSERT,	/* -062  Insert       */
VK_HOME,	/* -063  Home         */
VK_PRIOR,	/* -064  PgUp         */
VK_CAPITAL,	/* -065  Caps Lock    */
'A',		/* -066  A            */
'X',		/* -067  X            */
'F',		/* -068  F            */
'Y',		/* -069  Y            */
'J',		/* -070  J            */
'K',		/* -071  K            */
0xc0,		/* -072  @            */
0xba,		/* -073  ;            */
VK_RETURN,	/* -074  Return - Same as Keypad Enter */
VK_DIVIDE,	/* -075  Keypad /     */
VK_DECIMAL,	/* -076  Keypad Del   */
VK_DECIMAL,	/* -077  Keypad .     */
VK_NUMLOCK,	/* -078  Num Lock     */
VK_NEXT,	/* -079  PgDn         */
'2',		/* -080  "            */
0,		/* -081  Shift Lock   */
'S',		/* -082  S            */
'C',		/* -083  C            */
'G',		/* -084  G            */
'H',		/* -085  H            */
'N',		/* -086  N            */
'L',		/* -087  L            */
0xba,		/* -088  :            */
0xdd,		/* -089  ]            */
VK_DELETE,	/* -090  Delete       */
0,		/* -091  Keypad #     */
VK_MULTIPLY,	/* -092  Keypad *     */
0,		/* -093               */
0xbb,		/* -094  =/+          */
0xdc,		/* -095  Backslash    */
0,		/* -096               */
VK_TAB,		/* -097  TAB          */
'Z',		/* -098  Z            */
' ',		/* -099  Space        */
'V',		/* -100  V            */
'B',		/* -101  B            */
'M',		/* -102  M            */
0xbc,		/* -103  ,            */
0xbe,		/* -104  .            */
0xbf,		/* -105  /            */
VK_END,		/* -106  Copy/End     */
VK_NUMPAD0,	/* -107  Keypad 0     */
VK_NUMPAD1,	/* -108  Keypad 1     */
VK_NUMPAD3,	/* -109  Keypad 3     */
0,		/* -110               */
0,		/* -111               */
0,		/* -112               */
VK_ESCAPE,	/* -113  Escape       */
VK_F1,		/* -114  F1           */
VK_F2,		/* -115  F2           */
VK_F3,		/* -116  F3           */
VK_F5,		/* -117  F5           */
VK_F6,		/* -118  F6           */
VK_F8,		/* -119  F8           */
VK_F9,		/* -120  F9           */
0xde,		/* -121  #/~          */
VK_RIGHT,	/* -122  Right        */
VK_NUMPAD4,	/* -123  Keypad 4     */
VK_NUMPAD5,	/* -124  Keypad 5     */
VK_NUMPAD2,	/* -125  Keypad 2     */
0,		/* -126               */
0,		/* -127               */
0};		/* -128               */
#endif


int con_keyscan(int key)		/* Scan for keypress		*/
{
#ifdef CONKBD_PC
int tmp;
/* if (key > 0xff) return(GetAsyncKeyState(key & 0xff)); */
					/* Test code - direct API call	*/

if (key < 0x80) return(TRUE);		/* Scan range - unimplemented	*/
tmp=winmap[key ^ 0xff];			/* Get translated keycode	*/
if (tmp) return(GetAsyncKeyState(tmp));
  else return(0);			/* Return TRUE if key pressed	*/
#endif
}

