From da4ca8a49e384fa42fbecec4b15b3b0fa1699cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 7 Sep 2004 00:20:34 +0000 Subject: [PATCH] added keymap git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8880 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../input_server/devices/keyboard/Jamfile | 3 +- .../devices/keyboard/KeyboardInputDevice.h | 4 +- .../input_server/devices/keyboard/Keymap.cpp | 323 ++++++++++++++++++ .../input_server/devices/keyboard/Keymap.h | 38 +++ 4 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 src/add-ons/input_server/devices/keyboard/Keymap.cpp create mode 100644 src/add-ons/input_server/devices/keyboard/Keymap.h diff --git a/src/add-ons/input_server/devices/keyboard/Jamfile b/src/add-ons/input_server/devices/keyboard/Jamfile index ba25b27d49..047fe414c4 100644 --- a/src/add-ons/input_server/devices/keyboard/Jamfile +++ b/src/add-ons/input_server/devices/keyboard/Jamfile @@ -1,7 +1,8 @@ SubDir OBOS_TOP src add-ons input_server devices keyboard ; Addon keyboard : input_server/devices : - KeyboardInputDevice.cpp + KeyboardInputDevice.cpp + Keymap.cpp : false : be input_server ; diff --git a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h index 027a3e9725..f05ebf1058 100644 --- a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h +++ b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.h @@ -27,6 +27,7 @@ #ifndef __KEYBOARDINPUTDEVICE_H #define __KEYBOARDINPUTDEVICE_H +#include "Keymap.h" #include #include #include @@ -61,7 +62,8 @@ private: static int32 DeviceWatcher(void *arg); static char *GetShortName(const char *longName); - BList fDevices; + BList fDevices; + Keymap fKeymap; }; extern "C" BInputServerDevice *instantiate_input_device(); diff --git a/src/add-ons/input_server/devices/keyboard/Keymap.cpp b/src/add-ons/input_server/devices/keyboard/Keymap.cpp new file mode 100644 index 0000000000..e44645bfb9 --- /dev/null +++ b/src/add-ons/input_server/devices/keyboard/Keymap.cpp @@ -0,0 +1,323 @@ +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ +// +// Copyright (c) 2004, Haiku +// +// This software is part of the Haiku distribution and is covered +// by the Haiku license. +// +// +// File: Keymap.h +// Author: Jérôme Duval +// Description: Keyboard input server addon +// Created : September 7, 2004 +// +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ + +#include "Keymap.h" +#include +#include +#include +#include + +static void +print_key( char *chars, int32 offset ) +{ + int size = chars[offset++]; + + switch( size ) { + case 0: + // Not mapped + printf( "N/A" ); + break; + + case 1: + // 1-byte UTF-8/ASCII character + printf( "%c", chars[offset] ); + break; + + default: + // 2-, 3-, or 4-byte UTF-8 character + { + char *str = new char[size + 1]; + strncpy( str, &(chars[offset]), size ); + str[size] = 0; + printf( "%s", str ); + delete [] str; + } + break; + } + + printf( "\t" ); +} + + +void +Keymap::DumpKeymap() +{ + // Print a chart of the normal, shift, option, and option+shift + // keys. + printf( "Key #\tNormal\tShift\tCaps\tC+S\tOption\tO+S\tO+C\tO+C+S\tControl\n" ); + for( int idx = 0; idx < 128; idx++ ) { + printf( " 0x%x\t", idx ); + print_key( fChars, fKeys.normal_map[idx] ); + print_key( fChars, fKeys.shift_map[idx] ); + print_key( fChars, fKeys.caps_map[idx] ); + print_key( fChars, fKeys.caps_shift_map[idx] ); + print_key( fChars, fKeys.option_map[idx] ); + print_key( fChars, fKeys.option_shift_map[idx] ); + print_key( fChars, fKeys.option_caps_map[idx] ); + print_key( fChars, fKeys.option_caps_shift_map[idx] ); + print_key( fChars, fKeys.control_map[idx] ); + printf( "\n" ); + } + +} + + +Keymap::Keymap() : + fChars(NULL) +{ + key_map *keys; + get_key_map(&keys, &fChars); + + if (keys) + memcpy(&fKeys, keys, sizeof(key_map)); +} + + +/* we need to know if a key is a modifier key to choose + a valid key when several are pressed together +*/ +bool +Keymap::IsModifierKey(uint32 keyCode) +{ + if ((keyCode == fKeys.caps_key) + || (keyCode == fKeys.num_key) + || (keyCode == fKeys.scroll_key) + || (keyCode == fKeys.left_shift_key) + || (keyCode == fKeys.right_shift_key) + || (keyCode == fKeys.left_command_key) + || (keyCode == fKeys.right_command_key) + || (keyCode == fKeys.left_control_key) + || (keyCode == fKeys.right_control_key) + || (keyCode == fKeys.left_option_key) + || (keyCode == fKeys.right_option_key) + || (keyCode == fKeys.menu_key)) + return true; + return false; +} + + +// tell if a key is a dead key, needed for draw a dead key +uint8 +Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) +{ + int32 offset; + uint32 tableMask = 0; + + switch (modifiers & 0xcf) { + case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; tableMask = B_SHIFT_TABLE; break; + case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; tableMask = B_CAPS_TABLE; break; + case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; tableMask = B_CAPS_SHIFT_TABLE; break; + case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; tableMask = B_OPTION_TABLE; break; + case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; tableMask = B_OPTION_SHIFT_TABLE; break; + case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; tableMask = B_OPTION_CAPS_TABLE; break; + case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; tableMask = B_OPTION_CAPS_SHIFT_TABLE; break; + case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; tableMask = B_CONTROL_TABLE; break; + default: offset = fKeys.normal_map[keyCode]; tableMask = B_NORMAL_TABLE; break; + } + + if (offset<=0) + return 0; + uint32 numBytes = fChars[offset]; + + if (!numBytes) + return 0; + + char chars[4]; + strncpy(chars, &(fChars[offset+1]), numBytes ); + chars[numBytes] = 0; + + int32 deadOffsets[] = { + fKeys.acute_dead_key[1], + fKeys.grave_dead_key[1], + fKeys.circumflex_dead_key[1], + fKeys.dieresis_dead_key[1], + fKeys.tilde_dead_key[1] + }; + + uint32 deadTables[] = { + fKeys.acute_tables, + fKeys.grave_tables, + fKeys.circumflex_tables, + fKeys.dieresis_tables, + fKeys.tilde_tables + }; + + for (int32 i=0; i<5; i++) { + if ((deadTables[i] & tableMask) == 0) + continue; + + if (offset == deadOffsets[i]) + return i+1; + + uint32 deadNumBytes = fChars[deadOffsets[i]]; + + if (!deadNumBytes) + continue; + + if (strncmp(chars, &(fChars[deadOffsets[i]+1]), deadNumBytes ) == 0) { + return i+1; + } + } + return 0; +} + + +// tell if a key is a dead second key, needed for draw a dead second key +bool +Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) +{ + if (!activeDeadKey) + return false; + + int32 offset; + + switch (modifiers & 0xcf) { + case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; + case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; + case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; + case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; + case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; + case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; + case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; + case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; + default: offset = fKeys.normal_map[keyCode]; break; + } + + uint32 numBytes = fChars[offset]; + + if (!numBytes) + return false; + + int32* deadOffsets[] = { + fKeys.acute_dead_key, + fKeys.grave_dead_key, + fKeys.circumflex_dead_key, + fKeys.dieresis_dead_key, + fKeys.tilde_dead_key + }; + + int32 *deadOffset = deadOffsets[activeDeadKey-1]; + + for (int32 i=0; i<32; i++) { + if (offset == deadOffset[i]) + return true; + + uint32 deadNumBytes = fChars[deadOffset[i]]; + + if (!deadNumBytes) + continue; + + if (strncmp(&(fChars[offset+1]), &(fChars[deadOffset[i]+1]), deadNumBytes ) == 0) + return true; + i++; + } + return false; +} + + +// get the char for a key given modifiers and active dead key +void +Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, char** chars, int32* numBytes) +{ + int32 offset; + + *numBytes = 0; + *chars = NULL; + + // here we take NUMLOCK into account + if (modifiers & B_NUM_LOCK) + switch (keyCode) { + case 0x37: + case 0x38: + case 0x39: + case 0x48: + case 0x49: + case 0x4a: + case 0x58: + case 0x59: + case 0x5a: + case 0x64: + case 0x65: + modifiers ^= B_SHIFT_KEY; + } + + // here we choose the right map given the modifiers + switch (modifiers & 0xcf) { + case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; + case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; + case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; + case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; + case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; + case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; + case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; + case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; + default: offset = fKeys.normal_map[keyCode]; break; + } + + // here we get the char size + *numBytes = fChars[offset]; + + if (!*numBytes) + return; + + // here we take an potential active dead key + int32 *dead_key; + switch(activeDeadKey) { + case 1: dead_key = fKeys.acute_dead_key; break; + case 2: dead_key = fKeys.grave_dead_key; break; + case 3: dead_key = fKeys.circumflex_dead_key; break; + case 4: dead_key = fKeys.dieresis_dead_key; break; + case 5: dead_key = fKeys.tilde_dead_key; break; + default: + { + // if not dead, we copy and return the char + char *str = *chars = new char[*numBytes + 1]; + strncpy(str, &(fChars[offset+1]), *numBytes ); + str[*numBytes] = 0; + return; + } + } + + // if dead key, we search for our current offset char in the dead key offset table + // string comparison is needed + for (int32 i=0; i<32; i++) { + if (strncmp(&(fChars[offset+1]), &(fChars[dead_key[i]+1]), *numBytes ) == 0) { + *numBytes = fChars[dead_key[i+1]]; + + switch( *numBytes ) { + case 0: + // Not mapped + *chars = NULL; + break; + default: + // 1-, 2-, 3-, or 4-byte UTF-8 character + { + char *str = *chars = new char[*numBytes + 1]; + strncpy(str, &fChars[dead_key[i+1]+1], *numBytes ); + str[*numBytes] = 0; + } + break; + } + return; + } + i++; + } + + // if not found we return the current char mapped + *chars = new char[*numBytes + 1]; + strncpy(*chars, &(fChars[offset+1]), *numBytes ); + (*chars)[*numBytes] = 0; + +} diff --git a/src/add-ons/input_server/devices/keyboard/Keymap.h b/src/add-ons/input_server/devices/keyboard/Keymap.h new file mode 100644 index 0000000000..98db7f338c --- /dev/null +++ b/src/add-ons/input_server/devices/keyboard/Keymap.h @@ -0,0 +1,38 @@ +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ +// +// Copyright (c) 2004, Haiku +// +// This software is part of the Haiku distribution and is covered +// by the Haiku license. +// +// +// File: Keymap.h +// Author: Jérôme Duval +// Description: Keyboard input server addon +// Created : September 7, 2004 +// +// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ + +#ifndef KEYMAP_H +#define KEYMAP_H + +#include +#include + +class Keymap +{ +public: + Keymap(); + void DumpKeymap(); + bool IsModifierKey(uint32 keyCode); + uint8 IsDeadKey(uint32 keyCode, uint32 modifiers); + bool IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey); + void GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, char** chars, int32* numBytes); +private: + char *fChars; + key_map fKeys; + //uint32 fCharsSize; +}; + + +#endif //KEYMAP_H