From 3d1888960d61461991f0542413964bcf8df42c40 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 12 Apr 2018 14:17:51 +0800 Subject: Initial commit From fbterm 1.7.0, at https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/fbterm/fbterm-1.7.0.tar.gz Signed-off-by: Jeremy Kerr --- im/keycode.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 im/keycode.c (limited to 'im/keycode.c') diff --git a/im/keycode.c b/im/keycode.c new file mode 100644 index 0000000..d0c3b6d --- /dev/null +++ b/im/keycode.c @@ -0,0 +1,293 @@ +/* + * Copyright © 2008-2010 dragchan + * This file is part of FbTerm. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "input_key.h" + +static char key_down[NR_KEYS]; +static unsigned char shift_down[NR_SHIFT]; +static short shift_state; +static char lock_state; +static char cr_with_lf, applic_keypad, cursor_esco; +static int npadch; + +void init_keycode_state() +{ + npadch = -1; + shift_state = 0; + memset(key_down, 0, sizeof(char) * NR_KEYS); + memset(shift_down, 0, sizeof(char) * NR_SHIFT); + ioctl(STDIN_FILENO, KDGKBLED, &lock_state); +} + +void update_term_mode(char crlf, char appkey, char curo) +{ + cr_with_lf = crlf; + applic_keypad = appkey; + cursor_esco = curo; +} + +unsigned short keycode_to_keysym(unsigned short keycode, char down) +{ + if (keycode >= NR_KEYS) return K_HOLE; + + char rep = (down && key_down[keycode]); + key_down[keycode] = down; + + struct kbentry ke; + ke.kb_table = shift_state; + ke.kb_index = keycode; + + if (ioctl(STDIN_FILENO, KDGKBENT, &ke) == -1) return K_HOLE; + + if (KTYP(ke.kb_value) == KT_LETTER && (lock_state & K_CAPSLOCK)) { + ke.kb_table = shift_state ^ (1 << KG_SHIFT); + if (ioctl(STDIN_FILENO, KDGKBENT, &ke) == -1) return K_HOLE; + } + + if (ke.kb_value == K_HOLE || ke.kb_value == K_NOSUCHMAP) return K_HOLE; + + unsigned value = KVAL(ke.kb_value); + + switch (KTYP(ke.kb_value)) { + case KT_SPEC: + switch (ke.kb_value) { + case K_NUM: + if (applic_keypad) break; + case K_BARENUMLOCK: + case K_CAPS: + case K_CAPSON: + if (down && !rep) { + if (value == KVAL(K_NUM) || value == KVAL(K_BARENUMLOCK)) lock_state ^= K_NUMLOCK; + else if (value == KVAL(K_CAPS)) lock_state ^= K_CAPSLOCK; + else if (value == KVAL(K_CAPSON)) lock_state |= K_CAPSLOCK; + + ioctl(STDIN_FILENO, KDSKBLED, lock_state); + } + break; + + default: + break; + } + break; + + case KT_SHIFT: + if (value >= NR_SHIFT || rep) break; + + if (value == KVAL(K_CAPSSHIFT)) { + value = KVAL(K_SHIFT); + + if (down && (lock_state & K_CAPSLOCK)) { + lock_state &= ~K_CAPSLOCK; + ioctl(STDIN_FILENO, KDSKBLED, lock_state); + } + } + + if (down) shift_down[value]++; + else if (shift_down[value]) shift_down[value]--; + + if (shift_down[value]) shift_state |= (1 << value); + else shift_state &= ~(1 << value); + + break; + + case KT_LATIN: + case KT_LETTER: + case KT_FN: + case KT_PAD: + case KT_CONS: + case KT_CUR: + case KT_META: + case KT_ASCII: + break; + + default: + printf("not support!\n"); + break; + } + + return ke.kb_value; +} + +unsigned short keypad_keysym_redirect(unsigned short keysym) +{ + if (applic_keypad || KTYP(keysym) != KT_PAD || KVAL(keysym) >= NR_PAD) return keysym; + + #define KL(val) K(KT_LATIN, val) + static const unsigned short num_map[] = { + KL('0'), KL('1'), KL('2'), KL('3'), KL('4'), + KL('5'), KL('6'), KL('7'), KL('8'), KL('9'), + KL('+'), KL('-'), KL('*'), KL('/'), K_ENTER, + KL(','), KL('.'), KL('?'), KL('('), KL(')'), + KL('#') + }; + + static const unsigned short fn_map[] = { + K_INSERT, K_SELECT, K_DOWN, K_PGDN, K_LEFT, + K_P5, K_RIGHT, K_FIND, K_UP, K_PGUP, + KL('+'), KL('-'), KL('*'), KL('/'), K_ENTER, + K_REMOVE, K_REMOVE, KL('?'), KL('('), KL(')'), + KL('#') + }; + + if (lock_state & K_NUMLOCK) return num_map[keysym - K_P0]; + return fn_map[keysym - K_P0]; +} + + +static unsigned to_utf8(unsigned c, char *buf) +{ + unsigned index = 0; + + if (c < 0x80) + buf[index++] = c; + else if (c < 0x800) { + // 110***** 10****** + buf[index++] = 0xc0 | (c >> 6); + buf[index++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + if (c >= 0xD800 && c < 0xE000) + return index; + if (c == 0xFFFF) + return index; + // 1110**** 10****** 10****** + buf[index++] = 0xe0 | (c >> 12); + buf[index++] = 0x80 | ((c >> 6) & 0x3f); + buf[index++] = 0x80 | (c & 0x3f); + } else if (c < 0x200000) { + // 11110*** 10****** 10****** 10****** + buf[index++] = 0xf0 | (c >> 18); + buf[index++] = 0x80 | ((c >> 12) & 0x3f); + buf[index++] = 0x80 | ((c >> 6) & 0x3f); + buf[index++] = 0x80 | (c & 0x3f); + } + + return index; +} + + +char *keysym_to_term_string(unsigned short keysym, char down) +{ + static struct kbsentry kse; + char *buf = (char *)kse.kb_string; + *buf = 0; + + if (KTYP(keysym) != KT_SHIFT && !down) return buf; + + keysym = keypad_keysym_redirect(keysym); + unsigned index = 0, value = KVAL(keysym); + + + switch (KTYP(keysym)) { + case KT_LATIN: + case KT_LETTER: + if (value < KVAL(AC_START) || value > KVAL(AC_END)) index = to_utf8(value, buf); + break; + + case KT_FN: + kse.kb_func = value; + ioctl(STDIN_FILENO, KDGKBSENT, &kse); + index = strlen(buf); + break; + + case KT_SPEC: + if (keysym == K_ENTER) { + buf[index++] = '\r'; + if (cr_with_lf) buf[index++] = '\n'; + } else if (keysym == K_NUM && applic_keypad) { + buf[index++] = '\e'; + buf[index++] = 'O'; + buf[index++] = 'P'; + } + break; + + case KT_PAD: + if (applic_keypad && !shift_down[KG_SHIFT]) { + if (value < NR_PAD) { + static const char app_map[] = "pqrstuvwxylSRQMnnmPQS"; + + buf[index++] = '\e'; + buf[index++] = 'O'; + buf[index++] = app_map[value]; + } + } else if (keysym == K_P5 && !(lock_state & K_NUMLOCK)) { + buf[index++] = '\e'; + buf[index++] = (applic_keypad ? 'O' : '['); + buf[index++] = 'G'; + } + break; + + case KT_CUR: + if (value < 4) { + static const char cur_chars[] = "BDCA"; + + buf[index++] = '\e'; + buf[index++] = (cursor_esco ? 'O' : '['); + buf[index++] = cur_chars[value]; + } + break; + + case KT_META: { + long flag; + ioctl(STDIN_FILENO, KDGKBMETA, &flag); + + if (flag == K_METABIT) { + buf[index++] = 0x80 | value; + } else { + buf[index++] = '\e'; + buf[index++] = value; + } + break; + } + + case KT_SHIFT: + if (!down && npadch != -1) { + index = to_utf8(npadch, buf); + npadch = -1; + } + break; + + case KT_ASCII: + if (value < NR_ASCII) { + int base = 10; + + if (value >= KVAL(K_HEX0)) { + base = 16; + value -= KVAL(K_HEX0); + } + + if (npadch == -1) npadch = value; + else npadch = npadch * base + value; + } + break; + + default: + break; + } + + buf[index] = 0; + return buf; +} -- cgit v1.2.1