/*
 *  pocketop.c
 *
 *	0.0: Mar. 20, 2004 by Dai ISHIJIMA (for ek4)
 */

#include <stdio.h>
#include "pocketop.h"
#include "keychars.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 C_A 0x01
#define C_B 0x02
#define C_C 0x03
#define C_D 0x04
#define C_E 0x05
#define C_F 0x06
#define C_G 0x07
#define C_H 0x08
#define C_I 0x09
#define C_J 0x0a
#define C_K 0x0b
#define C_L 0x0c
#define C_M 0x0d
#define C_N 0x0e
#define C_O  0x0f
#define C_P 0x10
#define C_Q 0x11
#define C_R 0x12
#define C_S 0x13
#define C_T 0x14
#define C_U 0x15
#define C_V 0x16
#define C_W 0x17
#define C_X 0x18
#define C_Y 0x19
#define C_Z 0x1a

#define SQ '\''
#define DQ '"'
#define YEN '\x5c'

#define DEL 127
#define BTB HT
#define TAB HT

#define NOP -1
#define PUNCT -4
#define NUML -8
#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 UP CHAR_UP
#define DOWN CHAR_DOWN
#define LEFT CHAR_LEFT
#define RIGHT CHAR_RIGHT
#define KANJI CHAR_KANJI

#define KEY_RELEASE 0x80



/* 修飾キー (modifier) */
#define M_SHIFT 1
#define M_CTRL 2
#define M_NUM 4
#define SHIFTMASK 7

typedef struct {
    int keynum;		/* キー番号 */
    int scancode;	/* キーボードスキャンコード */
    int cc[8];
} p_keyinfo_t;

p_keyinfo_t p_keytables[] = {
    /*    code    norm  shift ctrl  c+s   +num */
    {  0, 0x00, { NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP}},
    {  1, 0x69, { TAB,  BTB,  TAB,  BTB,  ESC,  ESC,  ESC,  ESC}},
    {  2, 0x40, { ESC,  ESC,  ESC,  ESC,  ESC,  ESC,  ESC,  ESC}},
    /* 2/Date/40, 3/Address/48, 4/ToDo/50, 5/Memo/58 */
    {  6, 0x01, { 'q',  'Q',  C_Q,  C_Q,  '1',  '!',  '1',  '!'}},
    {  7, 0x09, { 'w',  'W',  C_W,  C_W,  '2',  '@',  NUL,  NUL}},
    {  8, 0x11, { 'e',  'E',  C_E,  C_E,  '3',  '#',  '3',  '#'}},
    {  9, 0x19, { 'r',  'R',  C_R,  C_R,  '4',  '$',  '4',  '$'}},
    { 10, 0x21, { 't',  'T',  C_T,  C_T,  '5',  '%',  '5',  '%'}},
    { 11, 0x29, { 'y',  'Y',  C_Y,  C_Y,  '6',  '^',  '6',  '^'}},
    { 12, 0x31, { 'u',  'U',  C_U,  C_U,  '7',  '&',  '7',  '&'}},
    { 13, 0x39, { 'i',  'I',  C_I,  C_I,  '8',  '*',  '8',  '*'}},
    { 14, 0x41, { 'o',  'O',  C_O,  C_O,  '9',  '(',  '9',  '('}},
    { 15, 0x49, { 'p',  'P',  C_P,  C_P,  '0',  ')',  '0',  ')'}},
    { 16, 0x51, { '-',  '_',  US,   US,   '/',  '+',  '/',  '+'}},
    { 17, 0x59, { BS,   DEL,  BS,   BS,   DEL,  BS,   DEL,  DEL}},
    { 18, 0x77, { NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP,  NOP}},
    { 19, 0x07, { 'a',  'A',  C_A,  C_A,  '`',  '`',  '`',  '`'}},
    { 20, 0x0f, { 's',  'S',  C_S,  C_S,  '~',  '~',  '~',  '~'}},
    { 21, 0x17, { 'd',  'D',  C_D,  C_D,  '/',  '/',  '/',  '/'}},
    { 22, 0x1f, { 'f',  'F',  C_F,  C_F,  '?',  '?',  '?',  '?'}},
    { 23, 0x27, { 'G',  'G',  C_G,  C_G,  '[',  '[',  '[',  '['}},
    { 24, 0x2f, { 'h',  'H',  C_H,  C_H,  ']',  ']',  ']',  ']'}},
    { 25, 0x32, { 'j',  'J',  C_J,  C_J,  '4',  '{',  '4',  '{'}},
    { 26, 0x3a, { 'k',  'K',  C_K,  C_K,  '5',  '}',  '5',  '}'}},
    { 27, 0x42, { 'l',  'L',  C_L,  C_L,  '6',  YEN,  '6',  YEN}},
    { 28, 0x4a, { ';',  ':',  ';',  ':',  '*',  '|',  '*',  '|'}},
    { 29, 0x52, { SQ,   DQ,   SQ,   DQ,   '=',  '=',  '=',  '='}},
    { 30, 0x5a, { CR,   NL,   CR,   NL,   CR,   NL,   CR,   NL }},
    { 31, 0x65, { LSFT, LSFT, LSFT, LSFT, LSFT, LSFT, LSFT, LSFT}},
    { 32, 0x03, { 'z',  'Z',  C_Z,  C_Z,  'z',  'Z',  'z',  'Z'}},
    { 33, 0x0b, { 'x',  'X',  C_X,  C_X,  'x',  'X',  'x',  'X'}},
    { 34, 0x13, { 'c',  'C',  C_C,  C_C,  'c',  'C',  'c',  'C'}},
    { 35, 0x1b, { 'v',  'V',  C_V,  C_V,  'v',  'V',  'v',  'V'}},
    { 36, 0x23, { 'b',  'B',  C_B,  C_B,  'b',  'B',  'b',  'B'}},
    { 37, 0x33, { 'n',  'N',  C_N,  C_N,  'n',  'N',  'n',  'N'}},
    { 38, 0x3b, { 'm',  'M',  C_M,  C_M,  '1',  '1',  '1',  '1'}},
    { 39, 0x43, { ',',  '<',  ',',  '<',  '2',  '<',  '2',  '<'}},
    { 40, 0x3b, { '.',  '>',  '.',  '>',  '3',  '>',  '3',  '>'}},
    { 41, 0x53, { UP,   UP,   UP,   UP,   '-',  '-',  '-',  '-'}},
    { 42, 0x7d, { RSFT, RSFT, RSFT, RSFT, RSFT, RSFT, RSFT, RSFT}},
    { 43, 0x6d, { CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL}},
    { 44, 0x76, { PUNCT,PUNCT,PUNCT,PUNCT,PUNCT,PUNCT,PUNCT,PUNCT}},
    { 45, 0x75, { KANJI,KANJI,KANJI,KANJI,KANJI,KANJI,KANJI,KANJI}},
    { 46, 0x6e, { NUML,  NUML,  NUML,  NUML,  NUML,  NUML,  NUML,  NUML}},
    { 47, 0x66, { ALT,  ALT,  ALT,  ALT,  ALT,  ALT,  ALT,  ALT}},
    { 48, 0x2b, { SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC}},
    { 49, 0x34, { SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC}},
    { 50, 0x3c, { '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0'}},
    { 51, 0x44, { LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT}},
    { 52, 0x4c, { DOWN, DOWN, DOWN, DOWN, DOWN, DOWN, DOWN, DOWN}},
    { 53, 0x54, { RIGHT,RIGHT,RIGHT,RIGHT,RIGHT,RIGHT,RIGHT,RIGHT}},
    { 54, 0x5b, { DEL,  BS,   DEL,  DEL,  BS,   DEL,  BS,   BS}},
    { -1,   -1, {  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1}},
};


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

    /* 入力データをキューに追加 */
    j = p;
    for (i = 0; (j < BUFSIZ) && (i < n); i++, j++) {
	keybuf[j] = buf[i];
    }
    if (j >= BUFSIZ) {
	fprintf(stderr, "%s: pocketopconv: buffer overflow\n", prog);
    }
    n = 0;
    i = 0;
    release = NO;
    while (i < j) {
	release = NO;
	code = keybuf[i] & 0x007f;
	release = keybuf[i] & 0x0080;
	for (k = 0; p_keytables[k].keynum >= 0; k++) {
	    if (p_keytables[k].scancode == code) {
		break;
	    }
	}
	if (p_keytables[k].scancode == code) {	/* キー発見 */
	    key = p_keytables[k].cc[shiftmode & SHIFTMASK];
	    if ((key == SHFT) || (key == LSFT) || (key == RSFT)) {
		if (release) {
		    shiftmode &= ~M_SHIFT;
		}
		else {
		    shiftmode |= M_SHIFT;
		}
	    }
	    if ((key == CTRL) || (key == LCTL) || (key == RCTL)) {
		if (release) {
		    shiftmode &= ~M_CTRL;
		}
		else {
		    shiftmode |= M_CTRL;
		}
	    }
	    if ((!release) && (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);
}
