/*
 *  keytab.c
 *
 *	0.0: Feb. 11, 2003 by Dai ISHIJIMA
 */

#include <stdio.h>
#include "ps2key.h"

#define YES 1
#define NO  0

extern char *prog;

#define NUL 0x00
#define SOH 0x01
#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define ACK 0x06
#define BEL 0x07
#define BS  0x08
#define HT  0x09
#define NL  0x0a
#define VT  0x0b
#define NP  0x0c
#define CR  0x0d
#define SO  0x0e
#define SI  0x0f
#define DLE 0x10
#define DC1 0x11
#define DC2 0x12
#define DC3 0x13
#define DC4 0x14
#define NAK 0x15
#define SYN 0x16
#define ETB 0x17
#define CAN 0x18
#define EM  0x19
#define SUB 0x1a
#define ESC 0x1b
#define FS  0x1c
#define GS  0x1d
#define RS  0x1e
#define US  0x1f
#define SPC 0x20

#define DEL 127
#define BTB HT

#define NOP -1
#define CAPS -16
#define SHFT -32
#define LSFT SHFT
#define RSFT SHFT
#define CTRL -64
#define LCTL CTRL
#define RCTL CTRL
#define ALT -128
#define LALT ALT
#define RALT ALT
#define L_NONE 0
#define L_CAPS 'c'

#define KEY_RELEASE 0xf0

#define M_SHIFT 1
#define M_CTRL 2
#define M_ALT 4
#define SHIFTMASK 7

typedef struct {
    int keynum;		/* キー番号 */
    int scancode;	/* キーボードスキャンコード */
#ifdef SLZAURUS
    signed char cc[8];
#else    
    char cc[8];
#endif    
#if 0
    char norm;		/* 通常発生すべき文字コード */
    char shft;		/* シフト状態 */
    char ctrl;		/* コントロール */
    char shct;		/* シフト+コントロール */
    char alt;		/* ALT */
    char alsh;
    char alct;
    char alsc;
#endif
    char lock;
} keyinfo_t;

keyinfo_t keytables[] = {
    {  0, 0x00, { NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP}, L_NONE},
    {  1, 0x0e, { '`',  '~',  NOP,  NOP,  '`',  '~',  NOP,  NOP}, L_NONE},
    {  2, 0x16, { '1',  '!',  NOP,  NOP,  '1',  '!',  NOP,  NOP}, L_NONE},
    {  3, 0x1e, { '2',  '@',  NUL,  NUL,  '2',  '@',  NUL,  NUL}, L_NONE},
    {  4, 0x26, { '3',  '#',  NOP,  NOP,  '3',  '#',  NOP,  NOP}, L_NONE},
    {  5, 0x25, { '4',  '$',  NOP,  NOP,  '4',  '$',  NOP,  NOP}, L_NONE},
    {  6, 0x2e, { '5',  '%',  NOP,  NOP,  '5',  '%',  NOP,  NOP}, L_NONE},
    {  7, 0x36, { '6',  '^',   RS,   RS,  '6',  '^',   RS,   RS}, L_NONE},
    {  8, 0x3d, { '7',  '&',  NOP,  NOP,  '7',  '&',  NOP,  NOP}, L_NONE},
    {  9, 0x3e, { '8',  '*',  NOP,  NOP,  '8',  '*',  NOP,  NOP}, L_NONE},
    { 10, 0x46, { '9',  '(',  NOP,  NOP,  '9',  '(',  NOP,  NOP}, L_NONE},
    { 11, 0x45, { '0',  ')',  NOP,  NOP,  '0',  ')',  NOP,  NOP}, L_NONE},
    { 12, 0x4e, { '-',  '_',   US,   US,  '-',  '_',   US,   US}, L_NONE},
    { 13, 0x55, { '=',  '+',  NOP,  NOP,  '=',  '+',  NOP,  NOP}, L_NONE},
    { 14, 0x6a, {0x5c,  '|',   FS,   FS, 0x5c,  '|',   FS,   FS}, L_NONE},
    { 15, 0x66, { DEL,  DEL,   BS,   BS,  DEL,  DEL,   BS,   BS}, L_NONE},
    { 16, 0x0d, {  HT,  BTB,  NOP,  NOP,   HT,  BTB,  NOP,  NOP}, L_NONE},
    { 17, 0x15, { 'q',  'Q',  DC1,  DC1,  'q',  'Q',  DC1,  DC1}, L_CAPS},
    { 18, 0x1d, { 'w',  'W',  ETB,  ETB,  'w',  'W',  ETB,  ETB}, L_CAPS},
    { 19, 0x24, { 'e',  'E',  ENQ,  ENQ,  'e',  'E',  ENQ,  ENQ}, L_CAPS},
    { 20, 0x2d, { 'r',  'R',  DC2,  DC2,  'r',  'R',  DC2,  DC2}, L_CAPS},
    { 21, 0x2c, { 't',  'T',  DC4,  DC4,  't',  'T',  DC4,  DC4}, L_CAPS},
    { 22, 0x35, { 'y',  'Y',   EM,   EM,  'y',  'Y',   EM,   EM}, L_CAPS},
    { 23, 0x3c, { 'u',  'U',  NAK,  NAK,  'u',  'U',  NAK,  NAK}, L_CAPS},
    { 24, 0x43, { 'i',  'I',   HT,   HT,  'i',  'I',   HT,   HT}, L_CAPS},
    { 25, 0x44, { 'o',  'O',   SI,   SI,  'o',  'O',   SI,   SI}, L_CAPS},
    { 26, 0x4d, { 'p',  'P',  DLE,  DLE,  'p',  'P',  DLE,  DLE}, L_CAPS},
    { 27, 0x54, { '[',  '{',  ESC,  ESC,  '[',  '{',  ESC,  ESC}, L_NONE},
    { 28, 0x5b, { ']',  '}',   GS,   GS,  ']',  '}',   GS,   GS}, L_NONE},
    { 29, 0x5d, {0x5c,  '|',   FS,   FS, 0x5c,  '|',   FS,   FS}, L_NONE},
    { 30, 0x58, {CAPS, CAPS, CAPS, CAPS, CAPS, CAPS, CAPS, CAPS}, L_NONE},
    { 31, 0x1c, { 'a',  'A',  SOH,  SOH,  'a',  'A',  SOH,  SOH}, L_CAPS},
    { 32, 0x1b, { 's',  'S',  DC3,  DC3,  's',  'S',  DC3,  DC3}, L_CAPS},
    { 33, 0x23, { 'd',  'D',  EOT,  EOT,  'd',  'D',  EOT,  EOT}, L_CAPS},
    { 34, 0x2b, { 'f',  'F',  ACK,  ACK,  'f',  'F',  ACK,  ACK}, L_CAPS},
    { 35, 0x34, { 'g',  'G',  BEL,  BEL,  'g',  'G',  BEL,  BEL}, L_CAPS},
    { 36, 0x33, { 'h',  'H',   BS,   BS,  'h',  'H',   BS,   BS}, L_CAPS},
    { 37, 0x3b, { 'j',  'J',   NL,   NL,  'j',  'J',   NL,   NL}, L_CAPS},
    { 38, 0x42, { 'k',  'K',   VT,   VT,  'k',  'K',   VT,   VT}, L_CAPS},
    { 39, 0x4b, { 'l',  'L',   NP,   NP,  'l',  'L',   NP,   NP}, L_CAPS},
    { 40, 0x4c, { ';',  ':',  NOP,  NOP,  ';',  ':',  NOP,  NOP}, L_NONE},
    { 41, 0x52, {0x27,  '"',  NOP,  NOP, 0x27,  '"',  NOP,  NOP}, L_NONE},
    { 42, 0x5d, { ESC,  ESC,  ESC,  ESC,  ESC,  ESC,  NOP,  ESC}, L_NONE},
    { 43, 0x5a, {  CR,   CR,   NL,   NL,   CR,   CR,   NL,   NL}, L_NONE},
    { 44, 0x12, {LSFT, LSFT, LSFT, LSFT, LSFT, LSFT, LSFT, LSFT}, L_NONE},
    { 45, 0x61, {0x5c,  '|',   FS,   FS, 0x5c,  '|',   FS,   FS}, L_NONE},
    { 46, 0x1a, { 'z',  'Z',  SUB,  SUB,  'z',  'Z',  SUB,  SUB}, L_CAPS},
    { 47, 0x22, { 'x',  'X',  CAN,  CAN,  'x',  'X',  CAN,  CAN}, L_CAPS},
    { 48, 0x21, { 'c',  'C',  ETX,  ETX,  'c',  'C',  ETX,  ETX}, L_CAPS},
    { 49, 0x2a, { 'v',  'V',  SYN,  SYN,  'v',  'V',  SYN,  SYN}, L_CAPS},
    { 50, 0x32, { 'b',  'B',  STX,  STX,  'b',  'B',  STX,  STX}, L_CAPS},
    { 51, 0x31, { 'n',  'N',   SO,   SO,  'n',  'N',   SO,   SO}, L_CAPS},
    { 52, 0x3a, { 'm',  'M',   CR,   CR,  'm',  'M',   CR,   CR}, L_CAPS},
    { 53, 0x41, { ',',  '<',  NOP,  NOP,  ',',  '<',  NOP,  NOP}, L_NONE},
    { 54, 0x49, { '.',  '>',  NOP,  NOP,  '.',  '>',  NOP,  NOP}, L_NONE},
    { 55, 0x4a, { '/',  '?',  NOP,  NOP,  '/',  '?',  NOP,  NOP}, L_NONE},
    { 56, 0x51, {0x5c,  '_',   FS,   US, 0x5c,  '_',   FS,   US}, L_NONE},
    { 57, 0x59, {RSFT, RSFT, RSFT, RSFT, RSFT, RSFT, RSFT, RSFT}, L_NONE},
    { 58, 0x14, {LCTL, LCTL, LCTL, LCTL, LCTL, LCTL, LCTL, LCTL}, L_NONE},
    { 59, 0x00, { NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP}, L_NONE},
    { 60, 0x11, {LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT}, L_NONE},
    { 61, 0x29, { SPC,  SPC,  NUL,  SPC,  SPC,  SPC,  NOP,  SPC}, L_NONE},
    { 62, 0xe011, {RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT}, L_NONE},
    { 63, 0x00, { NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP}, L_NONE},
    { 64, 0xe014, {RCTL, RCTL, RCTL, RCTL, RCTL, RCTL, RCTL, RCTL}, L_NONE},
    /* */
    {110, 0x76, { ESC,  ESC,  ESC,  ESC,  ESC,  ESC,  NOP,  ESC}, L_NONE},
    { -1,   -1, {  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1},   -1},
};


/* キーコードから文字に変換 */
int ps2conv(int n, char *buf)
{
    static unsigned char keybuf[BUFSIZ];
    static int p = 0;
    static int shiftmode = 0;
    int i, j, k;
    int release;
    int key;

    /* 入力データをキューに追加 */
    j = p;
    for (i = 0; (j < BUFSIZ) && (i < n); i++, j++) {
	keybuf[j] = buf[i];
    }
    if (j >= BUFSIZ) {
	fprintf(stderr, "%s: ps2conv: buffer overflow\n", prog);
    }
    n = 0;
    i = 0;
    release = NO;
    while (i < j) {
	release = NO;
	if (keybuf[i] == KEY_RELEASE) {
	    if (i + 1 >= j) {
		break;
	    }
	    ++i;
	    release = YES;
	}
	for (k = 0; keytables[k].keynum >= 0; k++) {
	    if (keytables[k].scancode == keybuf[i]) {
		break;
	    }
	}
	if (keytables[k].scancode == keybuf[i]) {	/* キー発見 */
	    key = keytables[k].cc[shiftmode & SHIFTMASK];
	    if ((key == SHFT) || (key == LSFT) || (key == RSFT)) {
		if (release == YES) {
		    shiftmode &= ~M_SHIFT;
		}
		else {
		    shiftmode |= M_SHIFT;
		}
	    }
	    if ((key == CTRL) || (key == LCTL) || (key == RCTL)) {
		if (release == YES) {
		    shiftmode &= ~M_CTRL;
		}
		else {
		    shiftmode |= M_CTRL;
		}
	    }
	    if ((key == ALT) || (key == LALT) || (key == RALT)) {
		if (release == YES) {
		    shiftmode &= ~M_ALT;
		}
		else {
		    shiftmode |= M_ALT;
		}
	    }
	    if ((release != YES) && (key >= 0)) {
		buf[n] = key;
		++n;
	    }
	}
#ifdef EBUG
	else {
	    fprintf(stderr, "unknown keycode %02x\n", keybuf[i]);
	}
#endif
	++i;
    }
    /* 処理できなかったデータをキューの先頭に移動 */
    for (p = 0; i < j; p++, i++) {
	keybuf[p] = keybuf[i];
    }
    return(n);
}
