Implemented full evdev keyboard text support
This is based on the Linux kernel driver, and has fallback mapping tables in case we aren't connected to a virtual terminal.
parent
49292705a9
commit
e0a40fb6a9
|
@ -23348,7 +23348,7 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
|
||||||
fi
|
fi
|
||||||
# Set up files for evdev input
|
# Set up files for evdev input
|
||||||
if test x$use_input_events = xyes; then
|
if test x$use_input_events = xyes; then
|
||||||
SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c"
|
SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*-*-cygwin* | *-*-mingw32*)
|
*-*-cygwin* | *-*-mingw32*)
|
||||||
|
|
|
@ -3123,7 +3123,7 @@ case "$host" in
|
||||||
fi
|
fi
|
||||||
# Set up files for evdev input
|
# Set up files for evdev input
|
||||||
if test x$use_input_events = xyes; then
|
if test x$use_input_events = xyes; then
|
||||||
SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c"
|
SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*-*-cygwin* | *-*-mingw32*)
|
*-*-cygwin* | *-*-mingw32*)
|
||||||
|
|
|
@ -30,27 +30,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SDL_evdev.h"
|
#include "SDL_evdev.h"
|
||||||
|
#include "SDL_evdev_kbd.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <limits.h> /* For the definition of PATH_MAX */
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#ifdef SDL_INPUT_LINUXKD
|
|
||||||
#include <linux/kd.h>
|
|
||||||
#include <linux/keyboard.h>
|
|
||||||
#include <linux/vt.h>
|
|
||||||
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_assert.h"
|
#include "SDL_assert.h"
|
||||||
#include "SDL_endian.h"
|
#include "SDL_endian.h"
|
||||||
#include "../../core/linux/SDL_udev.h"
|
|
||||||
#include "SDL_scancode.h"
|
#include "SDL_scancode.h"
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
|
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
|
||||||
|
#include "../../core/linux/SDL_udev.h"
|
||||||
|
|
||||||
/* These are not defined in older Linux kernel headers */
|
/* These are not defined in older Linux kernel headers */
|
||||||
#ifndef SYN_DROPPED
|
#ifndef SYN_DROPPED
|
||||||
|
@ -62,9 +56,6 @@
|
||||||
#define ABS_MT_POSITION_Y 0x36
|
#define ABS_MT_POSITION_Y 0x36
|
||||||
#define ABS_MT_TRACKING_ID 0x39
|
#define ABS_MT_TRACKING_ID 0x39
|
||||||
#endif
|
#endif
|
||||||
#ifndef K_OFF
|
|
||||||
#define K_OFF 0x04
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct SDL_evdevlist_item
|
typedef struct SDL_evdevlist_item
|
||||||
{
|
{
|
||||||
|
@ -103,12 +94,11 @@ typedef struct SDL_evdevlist_item
|
||||||
|
|
||||||
typedef struct SDL_EVDEV_PrivateData
|
typedef struct SDL_EVDEV_PrivateData
|
||||||
{
|
{
|
||||||
|
int ref_count;
|
||||||
|
int num_devices;
|
||||||
SDL_evdevlist_item *first;
|
SDL_evdevlist_item *first;
|
||||||
SDL_evdevlist_item *last;
|
SDL_evdevlist_item *last;
|
||||||
int num_devices;
|
SDL_EVDEV_keyboard_state *kbd;
|
||||||
int ref_count;
|
|
||||||
int console_fd;
|
|
||||||
int old_kb_mode;
|
|
||||||
} SDL_EVDEV_PrivateData;
|
} SDL_EVDEV_PrivateData;
|
||||||
|
|
||||||
#define _THIS SDL_EVDEV_PrivateData *_this
|
#define _THIS SDL_EVDEV_PrivateData *_this
|
||||||
|
@ -135,28 +125,6 @@ static Uint8 EVDEV_MouseButtons[] = {
|
||||||
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
|
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prevent keystrokes from reaching the tty */
|
|
||||||
static int SDL_EVDEV_mute_keyboard(int tty_fd, int* old_kb_mode)
|
|
||||||
{
|
|
||||||
if (ioctl(tty_fd, KDGKBMODE, old_kb_mode) < 0) {
|
|
||||||
return SDL_SetError("Failed to get keyboard mode during muting");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(tty_fd, KDSKBMODE, K_OFF) < 0) {
|
|
||||||
return SDL_SetError("Failed to set keyboard mode during muting");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the keyboard mode for given tty */
|
|
||||||
static void SDL_EVDEV_unmute_keyboard(int tty_fd, int old_kb_mode)
|
|
||||||
{
|
|
||||||
if (ioctl(tty_fd, KDSKBMODE, old_kb_mode) < 0) {
|
|
||||||
SDL_SetError("Failed to set keyboard mode during unmuting");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_EVDEV_Init(void)
|
SDL_EVDEV_Init(void)
|
||||||
{
|
{
|
||||||
|
@ -187,14 +155,7 @@ SDL_EVDEV_Init(void)
|
||||||
/* TODO: Scan the devices manually, like a caveman */
|
/* TODO: Scan the devices manually, like a caveman */
|
||||||
#endif /* SDL_USE_LIBUDEV */
|
#endif /* SDL_USE_LIBUDEV */
|
||||||
|
|
||||||
/* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
|
_this->kbd = SDL_EVDEV_kbd_init();
|
||||||
_this->console_fd = open("/dev/tty", O_RDONLY);
|
|
||||||
|
|
||||||
/* Mute the keyboard so keystrokes only generate evdev events and do not
|
|
||||||
leak through to the console */
|
|
||||||
if (_this->console_fd >= 0) {
|
|
||||||
SDL_EVDEV_mute_keyboard(_this->console_fd, &_this->old_kb_mode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_this->ref_count += 1;
|
_this->ref_count += 1;
|
||||||
|
@ -217,10 +178,7 @@ SDL_EVDEV_Quit(void)
|
||||||
SDL_UDEV_Quit();
|
SDL_UDEV_Quit();
|
||||||
#endif /* SDL_USE_LIBUDEV */
|
#endif /* SDL_USE_LIBUDEV */
|
||||||
|
|
||||||
if (_this->console_fd >= 0) {
|
SDL_EVDEV_kbd_quit(_this->kbd);
|
||||||
SDL_EVDEV_unmute_keyboard(_this->console_fd, _this->old_kb_mode);
|
|
||||||
close(_this->console_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove existing devices */
|
/* Remove existing devices */
|
||||||
while(_this->first != NULL) {
|
while(_this->first != NULL) {
|
||||||
|
@ -261,89 +219,6 @@ void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
|
||||||
}
|
}
|
||||||
#endif /* SDL_USE_LIBUDEV */
|
#endif /* SDL_USE_LIBUDEV */
|
||||||
|
|
||||||
#ifdef SDL_INPUT_LINUXKD
|
|
||||||
/* this logic is pulled from kbd_keycode() in drivers/tty/vt/keyboard.c in the
|
|
||||||
Linux kernel source */
|
|
||||||
static void SDL_EVDEV_do_text_input(unsigned short keycode)
|
|
||||||
{
|
|
||||||
char shift_state;
|
|
||||||
int locks_state;
|
|
||||||
struct kbentry kbe;
|
|
||||||
unsigned char type;
|
|
||||||
char text[2] = { 0 };
|
|
||||||
|
|
||||||
if (_this->console_fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
shift_state = TIOCL_GETSHIFTSTATE;
|
|
||||||
if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) {
|
|
||||||
/* TODO: error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbe.kb_table = shift_state;
|
|
||||||
kbe.kb_index = keycode;
|
|
||||||
|
|
||||||
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
|
|
||||||
/* TODO: error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kbe.kb_value == K_HOLE || kbe.kb_value == K_NOSUCHMAP) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbe.kb_value ^= 0xf000;
|
|
||||||
|
|
||||||
type = KTYP(kbe.kb_value);
|
|
||||||
|
|
||||||
if (type < 0xf0) {
|
|
||||||
/*
|
|
||||||
* FIXME: keysyms with a type below 0xf0 represent a unicode character
|
|
||||||
* which requires special handling due to dead characters, diacritics,
|
|
||||||
* etc. For perfect input a proper way to deal with such characters
|
|
||||||
* should be implemented.
|
|
||||||
*
|
|
||||||
* For reference, the only place I was able to find out about this
|
|
||||||
* special 0xf0 value was in an unused? couple of patches listed below.
|
|
||||||
*
|
|
||||||
* http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-keyboard.diff
|
|
||||||
* http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-console.diff
|
|
||||||
*/
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
type -= 0xf0;
|
|
||||||
|
|
||||||
/* if type is KT_LETTER then it can be affected by Caps Lock */
|
|
||||||
if (type == KT_LETTER) {
|
|
||||||
type = KT_LATIN;
|
|
||||||
|
|
||||||
if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) {
|
|
||||||
/* TODO: error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locks_state & K_CAPSLOCK) {
|
|
||||||
kbe.kb_table = shift_state ^ (1 << KG_SHIFT);
|
|
||||||
|
|
||||||
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
|
|
||||||
/* TODO: error */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */
|
|
||||||
if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80)
|
|
||||||
return;
|
|
||||||
|
|
||||||
*text = KVAL(kbe.kb_value);
|
|
||||||
SDL_SendKeyboardText(text);
|
|
||||||
}
|
|
||||||
#endif /* SDL_INPUT_LINUXKD */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SDL_EVDEV_Poll(void)
|
SDL_EVDEV_Poll(void)
|
||||||
{
|
{
|
||||||
|
@ -395,11 +270,9 @@ SDL_EVDEV_Poll(void)
|
||||||
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
|
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
|
||||||
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
|
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
|
||||||
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
|
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
|
||||||
#ifdef SDL_INPUT_LINUXKD
|
|
||||||
SDL_EVDEV_do_text_input(events[i].code);
|
|
||||||
#endif /* SDL_INPUT_LINUXKD */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
|
||||||
break;
|
break;
|
||||||
case EV_ABS:
|
case EV_ABS:
|
||||||
switch(events[i].code) {
|
switch(events[i].code) {
|
||||||
|
|
|
@ -0,0 +1,677 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#include "SDL_evdev_kbd.h"
|
||||||
|
|
||||||
|
#ifdef SDL_INPUT_LINUXKD
|
||||||
|
|
||||||
|
/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/kd.h>
|
||||||
|
#include <linux/keyboard.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
|
||||||
|
|
||||||
|
#include "../../events/SDL_events_c.h"
|
||||||
|
#include "SDL_evdev_kbd_default_accents.h"
|
||||||
|
#include "SDL_evdev_kbd_default_keymap.h"
|
||||||
|
|
||||||
|
/* These are not defined in older Linux kernel headers */
|
||||||
|
#ifndef K_UNICODE
|
||||||
|
#define K_UNICODE 0x03
|
||||||
|
#endif
|
||||||
|
#ifndef K_OFF
|
||||||
|
#define K_OFF 0x04
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler Tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define K_HANDLERS\
|
||||||
|
k_self, k_fn, k_spec, k_pad,\
|
||||||
|
k_dead, k_cons, k_cur, k_shift,\
|
||||||
|
k_meta, k_ascii, k_lock, k_lowercase,\
|
||||||
|
k_slock, k_dead2, k_brl, k_ignore
|
||||||
|
|
||||||
|
typedef void (k_handler_fn)(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag);
|
||||||
|
static k_handler_fn K_HANDLERS;
|
||||||
|
static k_handler_fn *k_handler[16] = { K_HANDLERS };
|
||||||
|
|
||||||
|
typedef void (fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
static void fn_enter(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
static void fn_num(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
static void fn_compose(SDL_EVDEV_keyboard_state *kbd);
|
||||||
|
|
||||||
|
static fn_handler_fn *fn_handler[] =
|
||||||
|
{
|
||||||
|
NULL, fn_enter, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, fn_caps_toggle,
|
||||||
|
fn_num, NULL, NULL, NULL,
|
||||||
|
NULL, fn_caps_on, fn_compose, NULL,
|
||||||
|
NULL, NULL, NULL, fn_num
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keyboard State
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SDL_EVDEV_keyboard_state
|
||||||
|
{
|
||||||
|
int console_fd;
|
||||||
|
int old_kbd_mode;
|
||||||
|
unsigned short **key_maps;
|
||||||
|
unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
|
||||||
|
SDL_bool dead_key_next;
|
||||||
|
int npadch; /* -1 or number assembled on pad */
|
||||||
|
struct kbdiacrs *accents;
|
||||||
|
unsigned int diacr;
|
||||||
|
SDL_bool rep; /* flag telling character repeat */
|
||||||
|
unsigned char lockstate;
|
||||||
|
unsigned char slockstate;
|
||||||
|
unsigned char ledflagstate;
|
||||||
|
char shift_state;
|
||||||
|
char text[128];
|
||||||
|
unsigned int text_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef DUMP_ACCENTS
|
||||||
|
static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
printf("static struct kbdiacrs default_accents = {\n");
|
||||||
|
printf(" %d,\n", kbd->accents->kb_cnt);
|
||||||
|
printf(" {\n");
|
||||||
|
for (i = 0; i < kbd->accents->kb_cnt; ++i) {
|
||||||
|
struct kbdiacr *diacr = &kbd->accents->kbdiacr[i];
|
||||||
|
printf(" { 0x%.2x, 0x%.2x, 0x%.2x },\n",
|
||||||
|
diacr->diacr, diacr->base, diacr->result);
|
||||||
|
}
|
||||||
|
while (i < 256) {
|
||||||
|
printf(" { 0x00, 0x00, 0x00 },\n");
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
printf(" }\n");
|
||||||
|
printf("};\n");
|
||||||
|
}
|
||||||
|
#endif /* DUMP_ACCENTS */
|
||||||
|
|
||||||
|
#ifdef DUMP_KEYMAP
|
||||||
|
static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||||
|
if (kbd->key_maps[i]) {
|
||||||
|
printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
|
||||||
|
for (j = 0; j < NR_KEYS; ++j) {
|
||||||
|
if ((j%8) == 0) {
|
||||||
|
printf("\n ");
|
||||||
|
}
|
||||||
|
printf("0x%.4x, ", kbd->key_maps[i][j]);
|
||||||
|
}
|
||||||
|
printf("\n};\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
|
||||||
|
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||||
|
if (kbd->key_maps[i]) {
|
||||||
|
printf(" default_key_map_%d,\n", i);
|
||||||
|
} else {
|
||||||
|
printf(" NULL,\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("};\n");
|
||||||
|
}
|
||||||
|
#endif /* DUMP_KEYMAP */
|
||||||
|
|
||||||
|
static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
kbd->key_maps = (unsigned short **)SDL_calloc(MAX_NR_KEYMAPS, sizeof(unsigned short *));
|
||||||
|
if (!kbd->key_maps) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||||
|
struct kbentry kbe;
|
||||||
|
|
||||||
|
kbe.kb_table = i;
|
||||||
|
kbe.kb_index = 0;
|
||||||
|
if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kbe.kb_value == K_NOSUCHMAP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd->key_maps[i] = (unsigned short *)SDL_malloc(NR_KEYS * sizeof(unsigned short));
|
||||||
|
if (!kbd->key_maps[i]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < NR_KEYS; ++j) {
|
||||||
|
kbe.kb_table = i;
|
||||||
|
kbe.kb_index = j;
|
||||||
|
if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kbd->key_maps[i][j] = (kbe.kb_value ^ 0xf000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_EVDEV_keyboard_state *
|
||||||
|
SDL_EVDEV_kbd_init(void)
|
||||||
|
{
|
||||||
|
SDL_EVDEV_keyboard_state *kbd;
|
||||||
|
int i;
|
||||||
|
char shift_state, flag_state;
|
||||||
|
|
||||||
|
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
|
||||||
|
if (!kbd) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd->npadch = -1;
|
||||||
|
|
||||||
|
/* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
|
||||||
|
kbd->console_fd = open("/dev/tty", O_RDONLY);
|
||||||
|
|
||||||
|
shift_state = TIOCL_GETSHIFTSTATE;
|
||||||
|
if (ioctl(kbd->console_fd, TIOCLINUX, &shift_state) == 0) {
|
||||||
|
kbd->shift_state = shift_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
|
||||||
|
kbd->ledflagstate = flag_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd->accents = &default_accents;
|
||||||
|
if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
|
||||||
|
/* No worries, we'll use the default accent table */
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd->key_maps = default_key_maps;
|
||||||
|
if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
|
||||||
|
/* Set the keyboard in UNICODE mode and load the keymaps */
|
||||||
|
ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
|
||||||
|
|
||||||
|
if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
|
||||||
|
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||||
|
if (kbd->key_maps[i]) {
|
||||||
|
SDL_free(kbd->key_maps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(kbd->key_maps);
|
||||||
|
|
||||||
|
kbd->key_maps = default_key_maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mute the keyboard so keystrokes only generate evdev events
|
||||||
|
* and do not leak through to the console
|
||||||
|
*/
|
||||||
|
ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DUMP_ACCENTS
|
||||||
|
SDL_EVDEV_dump_accents(kbd);
|
||||||
|
#endif
|
||||||
|
#ifdef DUMP_KEYMAP
|
||||||
|
SDL_EVDEV_dump_keymap(kbd);
|
||||||
|
#endif
|
||||||
|
return kbd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
if (!kbd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kbd->console_fd >= 0) {
|
||||||
|
/* Restore the original keyboard mode */
|
||||||
|
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||||
|
|
||||||
|
close(kbd->console_fd);
|
||||||
|
kbd->console_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kbd->key_maps && kbd->key_maps != default_key_maps) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
|
||||||
|
if (kbd->key_maps[i]) {
|
||||||
|
SDL_free(kbd->key_maps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(kbd->key_maps);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(kbd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper Functions.
|
||||||
|
*/
|
||||||
|
static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c)
|
||||||
|
{
|
||||||
|
/* c is already part of a UTF-8 sequence and safe to add as a character */
|
||||||
|
if (kbd->text_len < (sizeof(kbd->text)-1)) {
|
||||||
|
kbd->text[kbd->text_len++] = (char)c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c)
|
||||||
|
{
|
||||||
|
if (c < 0x80)
|
||||||
|
/* 0******* */
|
||||||
|
put_queue(kbd, c);
|
||||||
|
else if (c < 0x800) {
|
||||||
|
/* 110***** 10****** */
|
||||||
|
put_queue(kbd, 0xc0 | (c >> 6));
|
||||||
|
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||||
|
} else if (c < 0x10000) {
|
||||||
|
if (c >= 0xD800 && c < 0xE000)
|
||||||
|
return;
|
||||||
|
if (c == 0xFFFF)
|
||||||
|
return;
|
||||||
|
/* 1110**** 10****** 10****** */
|
||||||
|
put_queue(kbd, 0xe0 | (c >> 12));
|
||||||
|
put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
|
||||||
|
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||||
|
} else if (c < 0x110000) {
|
||||||
|
/* 11110*** 10****** 10****** 10****** */
|
||||||
|
put_queue(kbd, 0xf0 | (c >> 18));
|
||||||
|
put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
|
||||||
|
put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
|
||||||
|
put_queue(kbd, 0x80 | (c & 0x3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have a combining character DIACR here, followed by the character CH.
|
||||||
|
* If the combination occurs in the table, return the corresponding value.
|
||||||
|
* Otherwise, if CH is a space or equals DIACR, return DIACR.
|
||||||
|
* Otherwise, conclude that DIACR was not combining after all,
|
||||||
|
* queue it and return CH.
|
||||||
|
*/
|
||||||
|
static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
|
||||||
|
{
|
||||||
|
unsigned int d = kbd->diacr;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
kbd->diacr = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < kbd->accents->kb_cnt; i++) {
|
||||||
|
if (kbd->accents->kbdiacr[i].diacr == d &&
|
||||||
|
kbd->accents->kbdiacr[i].base == ch) {
|
||||||
|
return kbd->accents->kbdiacr[i].result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == ' ' || ch == d)
|
||||||
|
return d;
|
||||||
|
|
||||||
|
put_utf8(kbd, d);
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
return ((kbd->ledflagstate >> flag) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
kbd->ledflagstate |= 1 << flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
kbd->ledflagstate &= ~(1 << flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
kbd->lockstate ^= 1 << flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
kbd->slockstate ^= 1 << flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||||
|
{
|
||||||
|
kbd->ledflagstate ^= 1 << flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special function handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void fn_enter(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
if (kbd->diacr) {
|
||||||
|
put_utf8(kbd, kbd->diacr);
|
||||||
|
kbd->diacr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
if (kbd->rep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chg_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
if (kbd->rep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn_num(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
if (!kbd->rep)
|
||||||
|
chg_vc_kbd_led(kbd, K_NUMLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn_compose(SDL_EVDEV_keyboard_state *kbd)
|
||||||
|
{
|
||||||
|
kbd->dead_key_next = SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special key handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void k_ignore(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_spec(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
if (up_flag)
|
||||||
|
return;
|
||||||
|
if (value >= SDL_arraysize(fn_handler))
|
||||||
|
return;
|
||||||
|
if (fn_handler[value])
|
||||||
|
fn_handler[value](kbd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
if (up_flag)
|
||||||
|
return; /* no action, if this is a key release */
|
||||||
|
|
||||||
|
if (kbd->diacr)
|
||||||
|
value = handle_diacr(kbd, value);
|
||||||
|
|
||||||
|
if (kbd->dead_key_next) {
|
||||||
|
kbd->dead_key_next = SDL_FALSE;
|
||||||
|
kbd->diacr = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
put_utf8(kbd, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag)
|
||||||
|
{
|
||||||
|
if (up_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_dead(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
|
||||||
|
|
||||||
|
k_deadunicode(kbd, ret_diacr[value], up_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_dead2(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
k_deadunicode(kbd, value, up_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_cons(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_fn(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_cur(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
static const char pad_chars[] = "0123456789+-*/\015,.?()#";
|
||||||
|
|
||||||
|
if (up_flag)
|
||||||
|
return; /* no action, if this is a key release */
|
||||||
|
|
||||||
|
if (!vc_kbd_led(kbd, K_NUMLOCK)) {
|
||||||
|
/* unprintable action */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_queue(kbd, pad_chars[value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
int old_state = kbd->shift_state;
|
||||||
|
|
||||||
|
if (kbd->rep)
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* Mimic typewriter:
|
||||||
|
* a CapsShift key acts like Shift but undoes CapsLock
|
||||||
|
*/
|
||||||
|
if (value == KVAL(K_CAPSSHIFT)) {
|
||||||
|
value = KVAL(K_SHIFT);
|
||||||
|
if (!up_flag)
|
||||||
|
clr_vc_kbd_led(kbd, K_CAPSLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (up_flag) {
|
||||||
|
/*
|
||||||
|
* handle the case that two shift or control
|
||||||
|
* keys are depressed simultaneously
|
||||||
|
*/
|
||||||
|
if (kbd->shift_down[value])
|
||||||
|
kbd->shift_down[value]--;
|
||||||
|
} else
|
||||||
|
kbd->shift_down[value]++;
|
||||||
|
|
||||||
|
if (kbd->shift_down[value])
|
||||||
|
kbd->shift_state |= (1 << value);
|
||||||
|
else
|
||||||
|
kbd->shift_state &= ~(1 << value);
|
||||||
|
|
||||||
|
/* kludge */
|
||||||
|
if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
|
||||||
|
put_utf8(kbd, kbd->npadch);
|
||||||
|
kbd->npadch = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_meta(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
int base;
|
||||||
|
|
||||||
|
if (up_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (value < 10) {
|
||||||
|
/* decimal input of code, while Alt depressed */
|
||||||
|
base = 10;
|
||||||
|
} else {
|
||||||
|
/* hexadecimal input of code, while AltGr depressed */
|
||||||
|
value -= 10;
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kbd->npadch == -1)
|
||||||
|
kbd->npadch = value;
|
||||||
|
else
|
||||||
|
kbd->npadch = kbd->npadch * base + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_lock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
if (up_flag || kbd->rep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chg_vc_kbd_lock(kbd, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
k_shift(kbd, value, up_flag);
|
||||||
|
if (up_flag || kbd->rep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chg_vc_kbd_slock(kbd, value);
|
||||||
|
/* try to make Alt, oops, AltGr and such work */
|
||||||
|
if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
|
||||||
|
kbd->slockstate = 0;
|
||||||
|
chg_vc_kbd_slock(kbd, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void k_brl(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down)
|
||||||
|
{
|
||||||
|
unsigned char shift_final;
|
||||||
|
unsigned char type;
|
||||||
|
unsigned short *key_map;
|
||||||
|
unsigned short keysym;
|
||||||
|
|
||||||
|
if (!kbd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd->rep = (down == 2);
|
||||||
|
|
||||||
|
shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
|
||||||
|
key_map = kbd->key_maps[shift_final];
|
||||||
|
if (!key_map) {
|
||||||
|
kbd->slockstate = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycode < NR_KEYS) {
|
||||||
|
keysym = key_map[keycode];
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = KTYP(keysym);
|
||||||
|
|
||||||
|
if (type < 0xf0) {
|
||||||
|
if (down) {
|
||||||
|
put_utf8(kbd, keysym);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type -= 0xf0;
|
||||||
|
|
||||||
|
/* if type is KT_LETTER then it can be affected by Caps Lock */
|
||||||
|
if (type == KT_LETTER) {
|
||||||
|
type = KT_LATIN;
|
||||||
|
|
||||||
|
if (vc_kbd_led(kbd, K_CAPSLOCK)) {
|
||||||
|
key_map = kbd->key_maps[shift_final ^ (1 << KG_SHIFT)];
|
||||||
|
if (key_map) {
|
||||||
|
keysym = key_map[keycode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*k_handler[type])(kbd, keysym & 0xff, !down);
|
||||||
|
|
||||||
|
if (type != KT_SLOCK) {
|
||||||
|
kbd->slockstate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kbd->text_len > 0) {
|
||||||
|
kbd->text[kbd->text_len] = '\0';
|
||||||
|
SDL_SendKeyboardText(kbd->text);
|
||||||
|
kbd->text_len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !SDL_INPUT_LINUXKD */
|
||||||
|
|
||||||
|
SDL_EVDEV_keyboard_state *
|
||||||
|
SDL_EVDEV_kbd_init(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_INPUT_LINUXKD */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SDL_EVDEV_keyboard_state;
|
||||||
|
typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state;
|
||||||
|
|
||||||
|
extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void);
|
||||||
|
extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down);
|
||||||
|
extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state);
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct kbdiacrs default_accents = {
|
||||||
|
68,
|
||||||
|
{
|
||||||
|
{ 0x60, 0x41, 0xc0 },
|
||||||
|
{ 0x60, 0x61, 0xe0 },
|
||||||
|
{ 0x27, 0x41, 0xc1 },
|
||||||
|
{ 0x27, 0x61, 0xe1 },
|
||||||
|
{ 0x5e, 0x41, 0xc2 },
|
||||||
|
{ 0x5e, 0x61, 0xe2 },
|
||||||
|
{ 0x7e, 0x41, 0xc3 },
|
||||||
|
{ 0x7e, 0x61, 0xe3 },
|
||||||
|
{ 0x22, 0x41, 0xc4 },
|
||||||
|
{ 0x22, 0x61, 0xe4 },
|
||||||
|
{ 0x4f, 0x41, 0xc5 },
|
||||||
|
{ 0x6f, 0x61, 0xe5 },
|
||||||
|
{ 0x30, 0x41, 0xc5 },
|
||||||
|
{ 0x30, 0x61, 0xe5 },
|
||||||
|
{ 0x41, 0x41, 0xc5 },
|
||||||
|
{ 0x61, 0x61, 0xe5 },
|
||||||
|
{ 0x41, 0x45, 0xc6 },
|
||||||
|
{ 0x61, 0x65, 0xe6 },
|
||||||
|
{ 0x2c, 0x43, 0xc7 },
|
||||||
|
{ 0x2c, 0x63, 0xe7 },
|
||||||
|
{ 0x60, 0x45, 0xc8 },
|
||||||
|
{ 0x60, 0x65, 0xe8 },
|
||||||
|
{ 0x27, 0x45, 0xc9 },
|
||||||
|
{ 0x27, 0x65, 0xe9 },
|
||||||
|
{ 0x5e, 0x45, 0xca },
|
||||||
|
{ 0x5e, 0x65, 0xea },
|
||||||
|
{ 0x22, 0x45, 0xcb },
|
||||||
|
{ 0x22, 0x65, 0xeb },
|
||||||
|
{ 0x60, 0x49, 0xcc },
|
||||||
|
{ 0x60, 0x69, 0xec },
|
||||||
|
{ 0x27, 0x49, 0xcd },
|
||||||
|
{ 0x27, 0x69, 0xed },
|
||||||
|
{ 0x5e, 0x49, 0xce },
|
||||||
|
{ 0x5e, 0x69, 0xee },
|
||||||
|
{ 0x22, 0x49, 0xcf },
|
||||||
|
{ 0x22, 0x69, 0xef },
|
||||||
|
{ 0x2d, 0x44, 0xd0 },
|
||||||
|
{ 0x2d, 0x64, 0xf0 },
|
||||||
|
{ 0x7e, 0x4e, 0xd1 },
|
||||||
|
{ 0x7e, 0x6e, 0xf1 },
|
||||||
|
{ 0x60, 0x4f, 0xd2 },
|
||||||
|
{ 0x60, 0x6f, 0xf2 },
|
||||||
|
{ 0x27, 0x4f, 0xd3 },
|
||||||
|
{ 0x27, 0x6f, 0xf3 },
|
||||||
|
{ 0x5e, 0x4f, 0xd4 },
|
||||||
|
{ 0x5e, 0x6f, 0xf4 },
|
||||||
|
{ 0x7e, 0x4f, 0xd5 },
|
||||||
|
{ 0x7e, 0x6f, 0xf5 },
|
||||||
|
{ 0x22, 0x4f, 0xd6 },
|
||||||
|
{ 0x22, 0x6f, 0xf6 },
|
||||||
|
{ 0x2f, 0x4f, 0xd8 },
|
||||||
|
{ 0x2f, 0x6f, 0xf8 },
|
||||||
|
{ 0x60, 0x55, 0xd9 },
|
||||||
|
{ 0x60, 0x75, 0xf9 },
|
||||||
|
{ 0x27, 0x55, 0xda },
|
||||||
|
{ 0x27, 0x75, 0xfa },
|
||||||
|
{ 0x5e, 0x55, 0xdb },
|
||||||
|
{ 0x5e, 0x75, 0xfb },
|
||||||
|
{ 0x22, 0x55, 0xdc },
|
||||||
|
{ 0x22, 0x75, 0xfc },
|
||||||
|
{ 0x27, 0x59, 0xdd },
|
||||||
|
{ 0x27, 0x79, 0xfd },
|
||||||
|
{ 0x54, 0x48, 0xde },
|
||||||
|
{ 0x74, 0x68, 0xfe },
|
||||||
|
{ 0x73, 0x73, 0xdf },
|
||||||
|
{ 0x22, 0x79, 0xff },
|
||||||
|
{ 0x73, 0x7a, 0xdf },
|
||||||
|
{ 0x69, 0x6a, 0xff },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue