/* * Translate a raw key(scan code) to characters * * Copyright (C) 1997 Hung-Chi Chu * * This file is part of the Big5Con(Big5 Chinese Console) package. * * Big5Con 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. * * Big5Con 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 "big5con.h" static unsigned kbd_state = 0; static const u_char esc_code = 27; static int auto_cursor = 1; int altmeta = 0; struct fkeydef { u_char str[6]; u_char len; }; static struct fkeydef fkey_tab[64] = { /* 01-04 */ {"\033OP", 3}, {"\033OQ", 3}, {"\033OR", 3}, {"\033OS", 3}, /* 05-08 */ {"\033[15~", 5}, {"\033[17~", 5}, {"\033[18~", 5}, {"\033[19~", 5}, /* 09-12 */ {"\033[20~", 5}, {"\033[21~", 5}, {"\033[23~", 5}, {"\033[24~", 5}, /* 13-16 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 17-20 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 21-24 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 25-28 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 29-32 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 33-36 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 37-40 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 41-44 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 45-48 */ {"", 0}, {"", 0}, {"", 0}, {"", 0}, /* 49-52 */ {"\033[1~", 4}, {"\033OA", 3}, {"\033[5~", 4}, {"-", 1}, /* 53-56 */ {"\033OD", 3}, {"", 0}, {"\033OC", 3}, {"+", 1}, /* 57-60 */ {"\033[4~", 4}, {"\033OB", 3}, {"\033[6~", 4}, {"\033[2~", 4}, /* 61-64 */ {"\033[3~", 4}, {"", 0}, {"", 0}, {"", 0}, }; int kbd_leds; struct keymap vckmap; void trans_key(scancode) unsigned scancode; { static unsigned state = 0; unsigned keycode = (scancode & 0x7f); int press_down = ((scancode & 0x80) ? 0 : 1); #if __FreeBSD__ < 3 struct key_t *key; #else struct keyent_t *key; #endif unsigned num_shift = 0; int spcl_key = 0, res, cfd; unsigned char keychar; scancode &= 0xff; switch (state) { case 0x1D: state = 0; return; case 0xE1: state = (scancode == 0x1D) ? 0x1D : 0; return; case 0: switch (scancode) { case 0xE0: case 0xE1: state = scancode; return; case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: if (kbd_state & KEY_ALT_MASK) { if ((cfd = open("/dev/ttyv0", 0)) >= 0) { ioctl(cfd, VT_ACTIVATE, scancode - KEY_F1 + (kbd_state & 0x3) * 10 + 1); /* * woju: for Alt-F? fast switching kbd_state = 0; */ close(cfd); } return; } case KEY_F11: case KEY_F12: if (kbd_state & KEY_ALT_MASK) { if ((cfd = open("/dev/ttyv0", 0)) >= 0) { ioctl(cfd, VT_ACTIVATE, scancode - KEY_F11 + 11); /* * woju: for Alt-F? fast switching kbd_state = 0; */ close(cfd); } return; } } break; case 0xE0: state = 0; switch (keycode) { case KEY_CTRL_L: keycode = KEY_CTRL_R; break; case KEY_ALT_L: keycode = KEY_ALT_R; break; case KEY_ENTER: keycode = KEY_KP_ENTER; break; case KEY_DIV: keycode = KEY_KP_DIV; break; case KEY_KP_DOT: keycode = KEY_DEL; break; case KEY_KP_0: keycode = KEY_INS; break; case KEY_KP_1: keycode = KEY_END; break; case KEY_KP_2: keycode = KEY_DOWN; break; case KEY_KP_3: keycode = KEY_PGDN; break; case KEY_KP_4: keycode = KEY_LEFT; break; case KEY_KP_6: keycode = KEY_RIGHT; break; case KEY_KP_7: keycode = KEY_HOME; break; case KEY_KP_8: keycode = KEY_UP; break; case KEY_KP_9: keycode = KEY_PGUP; break; default: return; } break; } if (kbd_leds & LED_NUM) { switch (keycode) { case KEY_KP_DOT: case KEY_KP_0: case KEY_KP_1: case KEY_KP_2: case KEY_KP_3: case KEY_KP_4: case KEY_KP_5: case KEY_KP_6: case KEY_KP_7: case KEY_KP_8: case KEY_KP_9: num_shift = KEY_SHIFT_MASK; } } key = vckmap.key + keycode; keychar = key->map[(kbd_state & KEY_SHIFT_MASK) ^ num_shift]; if (!press_down) { /* release key */ if (key->spcl & (0x80 >> ((kbd_state & KEY_SHIFT_MASK) ^ num_shift))) { switch (keychar) { case LSH: case RSH: kbd_state &= ~KEY_SHIFT_MASK; break; case LCTR: case RCTR: kbd_state &= ~KEY_CTRL_MASK; break; case LALT: case RALT: kbd_state &= ~KEY_ALT_MASK; break; } } } else { /* press down */ if (key->spcl & (0x80 >> ((kbd_state & KEY_SHIFT_MASK) ^ num_shift))) { switch (keychar) { case LSH: case RSH: kbd_state |= KEY_SHIFT_MASK; break; case LCTR: case RCTR: kbd_state |= KEY_CTRL_MASK; break; case LALT: case RALT: kbd_state |= KEY_ALT_MASK; break; case CLK: kbd_leds ^= LED_CAP; ioctl(0, KDSETLED, kbd_leds); break; case NLK: kbd_leds ^= LED_NUM; ioctl(0, KDSETLED, kbd_leds); break; case SLK: kbd_leds ^= LED_SCR; ioctl(0, KDSETLED, kbd_leds); break; } res = trans_key2(keycode << 8, kbd_state | (kbd_leds << 4)); } else { switch (keycode) { case KEY_KP_0: case KEY_KP_1: case KEY_KP_2: case KEY_KP_3: case KEY_KP_4: case KEY_KP_5: case KEY_KP_6: case KEY_KP_7: case KEY_KP_8: case KEY_KP_9: case KEY_KP_DOT: case KEY_KP_ENTER: case KEY_KP_PLUS: case KEY_KP_MINUS: case KEY_KP_MULT: case KEY_KP_DIV: res = trans_key2((keycode << 8) | keychar, kbd_state | (kbd_leds << 4)); break; default: if (kbd_state == (KEY_ALT_MASK | KEY_CTRL_MASK) && keychar == 't') { auto_cursor ^= 1; return; } res = trans_key2(keychar, kbd_state | (kbd_leds << 4)); } } if (!res) { keychar = key->map[kbd_state ^ num_shift]; if (key->spcl & (0x80 >> (kbd_state ^ num_shift))) { if (keychar >= F_FN && keychar < (F_FN + 64)) { /* function key */ struct fkeydef *fkey; fkey = fkey_tab + keychar - F_FN; if (fkey->len) write(masterPty, fkey->str, fkey->len); switch (keychar) { case F_FN + 52: if (auto_cursor && isPrevW2()) write(masterPty, fkey->str, fkey->len); break; case F_FN + 54: if (auto_cursor && isNextW2()) write(masterPty, fkey->str, fkey->len); break; } } } else { if (isalpha(keychar) && (kbd_leds & LED_CAP)) { if (kbd_state & KEY_SHIFT_MASK) keychar = tolower(keychar); else keychar = toupper(keychar); } if (altmeta && kbd_state & KEY_ALT_MASK) write(masterPty, &esc_code, 1); write(masterPty, &keychar, 1); if (keychar == 8 && auto_cursor && isPrevW2()) write(masterPty, &keychar, 1); } } } } int is_kp_num(key) unsigned key; { switch (key >> 8) { case KEY_KP_0: case KEY_KP_1: case KEY_KP_2: case KEY_KP_3: case KEY_KP_4: case KEY_KP_5: case KEY_KP_6: case KEY_KP_7: case KEY_KP_8: case KEY_KP_9: if (key & 0xff) return (1); default: return (0); } }