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