summaryrefslogtreecommitdiffstats
path: root/im/keycode.c
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2018-04-12 14:17:51 +0800
committerJeremy Kerr <jk@ozlabs.org>2018-04-12 14:17:51 +0800
commit3d1888960d61461991f0542413964bcf8df42c40 (patch)
tree8752a833ae13d6b1cc5af4032e41d45490d688fa /im/keycode.c
downloadfbterm-3d1888960d61461991f0542413964bcf8df42c40.tar.gz
fbterm-3d1888960d61461991f0542413964bcf8df42c40.zip
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 <jk@ozlabs.org>
Diffstat (limited to 'im/keycode.c')
-rw-r--r--im/keycode.c293
1 files changed, 293 insertions, 0 deletions
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 <zgchan317@gmail.com>
+ * 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 <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <linux/kd.h>
+#include <linux/keyboard.h>
+#include <linux/input.h>
+#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;
+}
OpenPOWER on IntegriCloud