From b44c25de42ce39022f701d5637797b2f57e63679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 16 Apr 2010 07:47:41 +0000 Subject: [PATCH] * Factored out a single base class out of the three Keymap implementations we had in our tree. * Adapted Keymap, keyboard, and consoled to use it - the additional functionality is implemented via a subclass in the first two cases. * "keymap" will come next. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36328 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/shared/Keymap.h | 60 ++ .../input_server/devices/keyboard/Jamfile | 2 +- .../devices/keyboard/KeyboardInputDevice.cpp | 4 +- .../input_server/devices/keyboard/Keymap.cpp | 420 +------------- .../input_server/devices/keyboard/Keymap.h | 23 +- src/bin/consoled/Jamfile | 20 +- src/bin/consoled/consoled.cpp | 20 +- src/kits/shared/Jamfile | 3 + src/kits/shared/Keymap.cpp | 537 ++++++++++++++++++ src/preferences/keymap/Jamfile | 2 +- src/preferences/keymap/Keymap.cpp | 431 +------------- src/preferences/keymap/Keymap.h | 25 +- src/preferences/keymap/KeymapWindow.cpp | 6 +- 13 files changed, 667 insertions(+), 886 deletions(-) create mode 100644 headers/private/shared/Keymap.h create mode 100644 src/kits/shared/Keymap.cpp diff --git a/headers/private/shared/Keymap.h b/headers/private/shared/Keymap.h new file mode 100644 index 0000000000..464db33f09 --- /dev/null +++ b/headers/private/shared/Keymap.h @@ -0,0 +1,60 @@ +/* + * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@pinc-software.de. + */ +#ifndef _KEYMAP_H +#define _KEYMAP_H + + +#include +#include + + +class BKeymap { +public: + BKeymap(); + virtual ~BKeymap(); + + status_t SetTo(const char* path); + status_t SetTo(BDataIO& stream); + status_t SetToCurrent(); + status_t SetToDefault(); + void Unset(); + + bool IsModifierKey(uint32 keyCode) const; + uint32 Modifier(uint32 keyCode) const; + uint32 KeyForModifier(uint32 modifier) const; + uint8 IsDeadKey(uint32 keyCode, + uint32 modifiers, + bool* isEnabled = NULL) const; + bool IsDeadSecondKey(uint32 keyCode, + uint32 modifiers, + uint8 activeDeadKey) const; + void GetChars(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey, char** chars, + int32* numBytes) const; + + const key_map& Map() const { return fKeys; } + + bool operator==(const BKeymap& other) const; + bool operator!=(const BKeymap& other) const; + + BKeymap& operator=(const BKeymap& other); + +protected: + int32 Offset(uint32 keyCode, uint32 modifiers, + uint32* _table = NULL) const; + uint8 DeadKeyIndex(int32 offset) const; + +protected: + char* fChars; + key_map fKeys; + uint32 fCharsSize; +}; + + +#endif // KEYMAP_H diff --git a/src/add-ons/input_server/devices/keyboard/Jamfile b/src/add-ons/input_server/devices/keyboard/Jamfile index 9281a1ac04..5cb09b31b7 100644 --- a/src/add-ons/input_server/devices/keyboard/Jamfile +++ b/src/add-ons/input_server/devices/keyboard/Jamfile @@ -12,7 +12,7 @@ Addon keyboard : TeamMonitorWindow.cpp TeamListItem.cpp - : input_server be $(TARGET_LIBSUPC++) ; + : input_server be libshared.a $(TARGET_LIBSUPC++) ; Package haiku-inputkit-cvs : keyboard : diff --git a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp index 3af3b539a9..24d5921b40 100644 --- a/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp +++ b/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp @@ -531,8 +531,8 @@ KeyboardDevice::_UpdateSettings(uint32 opcode) if (opcode == 0 || opcode == B_KEY_MAP_CHANGED || opcode == B_KEY_LOCKS_CHANGED) { BAutolock lock(fKeymapLock); - fKeymap.LoadCurrent(); - fModifiers = fKeymap.Locks(); + fKeymap.RetrieveCurrent(); + fModifiers = fKeymap.Map().lock_settings; _UpdateLEDs(); fControlKey = fKeymap.KeyForModifier(B_LEFT_CONTROL_KEY); fCommandKey = fKeymap.KeyForModifier(B_LEFT_COMMAND_KEY); diff --git a/src/add-ons/input_server/devices/keyboard/Keymap.cpp b/src/add-ons/input_server/devices/keyboard/Keymap.cpp index c7ca672f34..5b44e155a7 100644 --- a/src/add-ons/input_server/devices/keyboard/Keymap.cpp +++ b/src/add-ons/input_server/devices/keyboard/Keymap.cpp @@ -13,11 +13,7 @@ #include #include #include -#ifdef CONSOLED -# include -#else -# include -#endif +#include #include #include @@ -64,6 +60,17 @@ print_key(char *chars, int32 offset) // #pragma mark - +Keymap::Keymap() +{ + RetrieveCurrent(); +} + + +Keymap::~Keymap() +{ +} + + void Keymap::DumpKeymap() { @@ -87,413 +94,20 @@ Keymap::DumpKeymap() } -Keymap::Keymap() - : - fChars(NULL) -{ -#ifndef CONSOLED - key_map *keys; - _get_key_map(&keys, &fChars, &fCharsSize); - - if (keys) { - memcpy(&fKeys, keys, sizeof(key_map)); - free(keys); - } -#endif -} - - -Keymap::~Keymap() -{ - free(fChars); -} - - -/* 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) -{ - return 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; -} - - -//! We need to know a modifier for a key -uint32 -Keymap::Modifier(uint32 keyCode) -{ - if (keyCode == fKeys.caps_key) - return B_CAPS_LOCK; - if (keyCode == fKeys.num_key) - return B_NUM_LOCK; - if (keyCode == fKeys.scroll_key) - return B_SCROLL_LOCK; - if (keyCode == fKeys.left_shift_key) - return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.right_shift_key) - return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.left_command_key) - return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.right_command_key) - return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.left_control_key) - return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.right_control_key) - return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.left_option_key) - return B_LEFT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.right_option_key) - return B_RIGHT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.menu_key) - return B_MENU_KEY; - - return 0; -} - - -uint32 -Keymap::KeyForModifier(uint32 modifier) -{ - if (modifier == B_CAPS_LOCK) - return fKeys.caps_key; - if (modifier == B_NUM_LOCK) - return fKeys.num_key; - if (modifier == B_SCROLL_LOCK) - return fKeys.scroll_key; - if (modifier == B_LEFT_SHIFT_KEY || modifier == B_SHIFT_KEY) - return fKeys.left_shift_key; - if (modifier == B_RIGHT_SHIFT_KEY) - return fKeys.right_shift_key; - if (modifier == B_LEFT_COMMAND_KEY || modifier == B_COMMAND_KEY) - return fKeys.left_command_key; - if (modifier == B_RIGHT_COMMAND_KEY) - return fKeys.right_command_key; - if (modifier == B_LEFT_CONTROL_KEY || modifier == B_CONTROL_KEY) - return fKeys.left_control_key; - if (modifier == B_RIGHT_CONTROL_KEY) - return fKeys.right_control_key; - if (modifier == B_LEFT_OPTION_KEY || modifier == B_OPTION_KEY) - return fKeys.left_option_key; - if (modifier == B_RIGHT_OPTION_KEY) - return fKeys.right_option_key; - if (modifier == B_MENU_KEY) - return fKeys.menu_key; - - return 0; -} - - -//! Tell if a key is a dead key, needed for draw a dead key -uint8 -Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) -{ - if (keyCode >= 256) - return 0; - - 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 || offset > fCharsSize) - 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)) - 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 || keyCode >= 256) - 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; - } - - if (offset <= 0 || offset > fCharsSize) - return false; - - 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)) - 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) -{ - *numBytes = 0; - *chars = NULL; - - if (keyCode >= 256) - return; - - // 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; - break; - } - } - - int32 offset; - - // 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; - } - - if (offset <= 0) - return; - - // here we get the char size - *numBytes = fChars[offset]; - if (!*numBytes) - return; - - // here we take an potential active dead key - int32 *deadKey; - switch (activeDeadKey) { - case 1: deadKey = fKeys.acute_dead_key; break; - case 2: deadKey = fKeys.grave_dead_key; break; - case 3: deadKey = fKeys.circumflex_dead_key; break; - case 4: deadKey = fKeys.dieresis_dead_key; break; - case 5: deadKey = fKeys.tilde_dead_key; break; - default: - { - // if not dead, we copy and return the char - char *str = *chars = new (std::nothrow) char[*numBytes + 1]; - if (str == NULL) { - *numBytes = 0; - return; - } - 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[deadKey[i] + 1]), *numBytes) == 0) { - *numBytes = fChars[deadKey[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 (std::nothrow) char[*numBytes + 1]; - if (str == NULL) { - *numBytes = 0; - return; - } - strncpy(str, &fChars[deadKey[i + 1] + 1], *numBytes); - str[*numBytes] = 0; - break; - } - } - return; - } - i++; - } - - // if not found we return the whole sequence (the dead key itself plus - // the following char) - int32 deadKeyNumBytes = fChars[deadKey[1]]; - int32 fullNumBytes = deadKeyNumBytes + *numBytes; - *chars = new (std::nothrow) char[fullNumBytes + 1]; - if (*chars == NULL) { - *numBytes = 0; - return; - } - strncpy(*chars, &fChars[deadKey[1] + 1], deadKeyNumBytes); - strncpy(*chars + deadKeyNumBytes, &fChars[offset + 1], *numBytes); - *numBytes = fullNumBytes; - (*chars)[fullNumBytes] = 0; -} - - status_t -Keymap::LoadCurrent() +Keymap::RetrieveCurrent() { -#ifndef CONSOLED - key_map* keys = NULL; - free(fChars); - fChars = NULL; + Unset(); - _get_key_map(&keys, &fChars, &fCharsSize); + key_map* keys; + _get_key_map(&keys, &fChars, (ssize_t*)&fCharsSize); if (!keys) { fprintf(stderr, "error while getting current keymap!\n"); return B_ERROR; } + memcpy(&fKeys, keys, sizeof(fKeys)); free(keys); return B_OK; -#else // CONSOLED - char path[PATH_MAX]; - status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, - path, sizeof(path)); - if (status != B_OK) - return status; - - strlcat(path, "/Key_map", sizeof(path)); - int file = open(path, O_RDONLY); - if (file < 0) - return errno; - - if (read(file, &fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys)) { - fprintf(stderr, "error reading keymap keys\n"); - return B_BAD_VALUE; - } - - for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) - ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); - - if (read(file, &fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32)) { - fprintf(stderr, "error reading keymap size\n"); - return B_BAD_VALUE; - } - - fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); - if (fCharsSize < 0) - return B_BAD_VALUE; - - fChars = new char[fCharsSize]; - - if (read(file, fChars, fCharsSize) < 0) { - fprintf(stderr, "error reading keymap chars\n"); - return B_ERROR; - } - - return B_OK; -#endif // CONSOLED } diff --git a/src/add-ons/input_server/devices/keyboard/Keymap.h b/src/add-ons/input_server/devices/keyboard/Keymap.h index 478381d796..9007ef3dd0 100644 --- a/src/add-ons/input_server/devices/keyboard/Keymap.h +++ b/src/add-ons/input_server/devices/keyboard/Keymap.h @@ -1,5 +1,5 @@ /* - * Copyright 2004, Haiku. + * Copyright 2004-2010, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -9,33 +9,18 @@ #define KEYMAP_H -#include +#include #include -class Keymap { +class Keymap : public BKeymap { public: Keymap(); ~Keymap(); void DumpKeymap(); - bool IsModifierKey(uint32 keyCode); - uint32 Modifier(uint32 keyCode); - uint32 KeyForModifier(uint32 modifier); - 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); - uint32 Locks() { return fKeys.lock_settings; }; - status_t LoadCurrent(); - -private: - char* fChars; - key_map fKeys; - ssize_t fCharsSize; + status_t RetrieveCurrent(); }; diff --git a/src/bin/consoled/Jamfile b/src/bin/consoled/Jamfile index 953b585376..df42f286e9 100644 --- a/src/bin/consoled/Jamfile +++ b/src/bin/consoled/Jamfile @@ -1,25 +1,9 @@ SubDir HAIKU_TOP src bin consoled ; -UsePrivateHeaders input ; -UsePrivateHeaders kernel ; +UsePrivateHeaders input kernel shared ; UseHeaders [ FDirName $(HAIKU_TOP) src apps terminal ] ; -UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) servers input ] ; - -SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons input_server devices - keyboard ] ; -SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers input ] ; - -{ - local defines = [ FDefines CONSOLED ] ; - SubDirCcFlags $(defines) -Wall -Wno-multichar ; - SubDirC++Flags $(defines) -Wall -Wno-multichar ; -} Application consoled : consoled.cpp - - Keymap.cpp - : $(TARGET_LIBSUPC++) + : be libshared.a $(TARGET_LIBSUPC++) ; - -Includes [ FGristFiles consoled.cpp ] : SystemKeymap.h ; diff --git a/src/bin/consoled/consoled.cpp b/src/bin/consoled/consoled.cpp index 0034072764..41557d64a6 100644 --- a/src/bin/consoled/consoled.cpp +++ b/src/bin/consoled/consoled.cpp @@ -16,14 +16,13 @@ #include #include +#include #include #include #include #include - -#include "SystemKeymap.h" -#include "Keymap.h" +#include struct console; @@ -91,8 +90,19 @@ keyboard_reader(void* arg) uint8 activeDeadKey = 0; uint32 modifiers = 0; - Keymap keymap; - keymap.LoadCurrent(); + BKeymap keymap; + // Load current keymap from disk (we can't talk to the input server) + // TODO: find a better way (we shouldn't have to care about the on-disk + // location) + char path[PATH_MAX]; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, + path, sizeof(path)); + if (status == B_OK) { + strlcat(path, "/Key_map", sizeof(path)); + status = keymap.SetTo(path); + } + if (status != B_OK) + keymap.SetToDefault(); for (;;) { raw_key_info rawKeyInfo; diff --git a/src/kits/shared/Jamfile b/src/kits/shared/Jamfile index ef4a3d58d4..ec2c70dda6 100644 --- a/src/kits/shared/Jamfile +++ b/src/kits/shared/Jamfile @@ -5,6 +5,7 @@ AddSubDirSupportedPlatforms libbe_test ; UseLibraryHeaders agg ; UsePrivateHeaders shared libbe ; +UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) servers input ] ; # for RWLockManager only UsePrivateSystemHeaders ; @@ -17,12 +18,14 @@ StaticLibrary libshared.a : CommandPipe.cpp DragTrackingFilter.cpp HashString.cpp + Keymap.cpp RWLockManager.cpp ShakeTrackingFilter.cpp StringForSize.cpp Variant.cpp ; +Includes [ FGristFiles Keymap.cpp ] : SystemKeymap.h ; UseLibraryHeaders mapm ; diff --git a/src/kits/shared/Keymap.cpp b/src/kits/shared/Keymap.cpp new file mode 100644 index 0000000000..8b864c5bfa --- /dev/null +++ b/src/kits/shared/Keymap.cpp @@ -0,0 +1,537 @@ +/* + * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@pinc-software.de. + */ + + +#include + +#include + +#include +#include + +#include +#include + +#include "SystemKeymap.h" + // generated by the build system + + +// Private only at this point, as we might want to improve the dead key +// implementation in the future +enum dead_key_index { + kDeadKeyAcute = 1, + kDeadKeyGrave, + kDeadKeyCircumflex, + kDeadKeyDiaeresis, + kDeadKeyTilde +}; + + +static const uint32 kModifierKeys = B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY + | B_CAPS_LOCK | B_OPTION_KEY | B_MENU_KEY; + + +BKeymap::BKeymap() + : + fChars(NULL), + fCharsSize(0) +{ + Unset(); +} + + +BKeymap::~BKeymap() +{ + delete[] fChars; +} + + +/*! Load a map from a file. + File format in big endian: + struct key_map + uint32 size of following charset + charset (offsets go into this with size of character followed by + character) +*/ +status_t +BKeymap::SetTo(const char* path) +{ + BFile file; + status_t status = file.SetTo(path, B_READ_ONLY); + if (status != B_OK) + return status; + + return SetTo(file); +} + + +status_t +BKeymap::SetTo(BDataIO& stream) +{ + if (stream.Read(&fKeys, sizeof(fKeys)) < 1) + return B_IO_ERROR; + + // convert from big-endian + for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) { + ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); + } + + if (fKeys.version != 3) + return B_BAD_DATA; + + if (stream.Read(&fCharsSize, sizeof(uint32)) < 1) + return B_IO_ERROR; + + fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); + if (fCharsSize > 16 * 1024) { + Unset(); + return B_BAD_DATA; + } + + delete[] fChars; + fChars = new char[fCharsSize]; + + if (stream.Read(fChars, fCharsSize) != (ssize_t)fCharsSize) { + Unset(); + return B_IO_ERROR; + } + + return B_OK; +} + + +status_t +BKeymap::SetToCurrent() +{ +#if (defined(__BEOS__) || defined(__HAIKU__)) + key_map* keys = NULL; + get_key_map(&keys, &fChars); + if (!keys) + return B_ERROR; + + memcpy(&fKeys, keys, sizeof(fKeys)); + free(keys); + return B_OK; +#else // ! __BEOS__ + fprintf(stderr, "Unsupported operation on this platform!\n"); + exit(1); +#endif // ! __BEOS__ +} + + +status_t +BKeymap::SetToDefault() +{ + fKeys = kSystemKeymap; + fCharsSize = kSystemKeyCharsSize; + + fChars = new (std::nothrow) char[fCharsSize]; + if (fChars == NULL) { + Unset(); + return B_NO_MEMORY; + } + + memcpy(fChars, kSystemKeyChars, fCharsSize); + return B_OK; +} + + +void +BKeymap::Unset() +{ + delete fChars; + fChars = NULL; + fCharsSize = 0; + + memset(&fKeys, 0, sizeof(fKeys)); +} + + +/*! We need to know if a key is a modifier key to choose + a valid key when several are pressed together +*/ +bool +BKeymap::IsModifierKey(uint32 keyCode) const +{ + return keyCode == fKeys.caps_key + || keyCode == fKeys.num_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; +} + + +//! We need to know a modifier for a key +uint32 +BKeymap::Modifier(uint32 keyCode) const +{ + if (keyCode == fKeys.caps_key) + return B_CAPS_LOCK; + if (keyCode == fKeys.num_key) + return B_NUM_LOCK; + if (keyCode == fKeys.scroll_key) + return B_SCROLL_LOCK; + if (keyCode == fKeys.left_shift_key) + return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; + if (keyCode == fKeys.right_shift_key) + return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; + if (keyCode == fKeys.left_command_key) + return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; + if (keyCode == fKeys.right_command_key) + return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; + if (keyCode == fKeys.left_control_key) + return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; + if (keyCode == fKeys.right_control_key) + return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; + if (keyCode == fKeys.left_option_key) + return B_LEFT_OPTION_KEY | B_OPTION_KEY; + if (keyCode == fKeys.right_option_key) + return B_RIGHT_OPTION_KEY | B_OPTION_KEY; + if (keyCode == fKeys.menu_key) + return B_MENU_KEY; + + return 0; +} + + +uint32 +BKeymap::KeyForModifier(uint32 modifier) const +{ + if (modifier == B_CAPS_LOCK) + return fKeys.caps_key; + if (modifier == B_NUM_LOCK) + return fKeys.num_key; + if (modifier == B_SCROLL_LOCK) + return fKeys.scroll_key; + if (modifier == B_LEFT_SHIFT_KEY || modifier == B_SHIFT_KEY) + return fKeys.left_shift_key; + if (modifier == B_RIGHT_SHIFT_KEY) + return fKeys.right_shift_key; + if (modifier == B_LEFT_COMMAND_KEY || modifier == B_COMMAND_KEY) + return fKeys.left_command_key; + if (modifier == B_RIGHT_COMMAND_KEY) + return fKeys.right_command_key; + if (modifier == B_LEFT_CONTROL_KEY || modifier == B_CONTROL_KEY) + return fKeys.left_control_key; + if (modifier == B_RIGHT_CONTROL_KEY) + return fKeys.right_control_key; + if (modifier == B_LEFT_OPTION_KEY || modifier == B_OPTION_KEY) + return fKeys.left_option_key; + if (modifier == B_RIGHT_OPTION_KEY) + return fKeys.right_option_key; + if (modifier == B_MENU_KEY) + return fKeys.menu_key; + + return 0; +} + + +/*! Checks whether a key is a dead key. + If it is, the enabled/disabled state of that dead key will be passed + out via isEnabled (isEnabled is not touched for non-dead keys). +*/ +uint8 +BKeymap::IsDeadKey(uint32 keyCode, uint32 modifiers, bool* _isEnabled) const +{ + uint32 tableMask = 0; + int32 offset = Offset(keyCode, modifiers, &tableMask); + uint8 deadKeyIndex = DeadKeyIndex(offset); + if (deadKeyIndex > 0 && _isEnabled != NULL) { + uint32 deadTables[] = { + fKeys.acute_tables, + fKeys.grave_tables, + fKeys.circumflex_tables, + fKeys.dieresis_tables, + fKeys.tilde_tables + }; + *_isEnabled = (deadTables[deadKeyIndex - 1] & tableMask) != 0; + } + + return deadKeyIndex; +} + + +//! Tell if a key is a dead second key. +bool +BKeymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey) const +{ + if (!activeDeadKey) + return false; + + int32 offset = Offset(keyCode, modifiers); + if (offset < 0) + return false; + + uint32 numBytes = fChars[offset]; + if (!numBytes) + return false; + + const int32* deadOffsets[] = { + fKeys.acute_dead_key, + fKeys.grave_dead_key, + fKeys.circumflex_dead_key, + fKeys.dieresis_dead_key, + fKeys.tilde_dead_key + }; + + const 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 +BKeymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, + char** chars, int32* numBytes) const +{ + *numBytes = 0; + *chars = NULL; + + if (keyCode > 128 || fChars == NULL) + return; + + // here we take NUMLOCK into account + if ((modifiers & B_NUM_LOCK) != 0) { + 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; + } + } + + int32 offset = Offset(keyCode, modifiers); + if (offset < 0) + return; + + // here we get the char size + *numBytes = fChars[offset]; + if (!*numBytes) + return; + + // here we take an potential active dead key + const int32* deadKey; + switch (activeDeadKey) { + case kDeadKeyAcute: + deadKey = fKeys.acute_dead_key; + break; + case kDeadKeyGrave: + deadKey = fKeys.grave_dead_key; + break; + case kDeadKeyCircumflex: + deadKey = fKeys.circumflex_dead_key; + break; + case kDeadKeyDiaeresis: + deadKey = fKeys.dieresis_dead_key; + break; + case kDeadKeyTilde: + deadKey = 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[deadKey[i] + 1], *numBytes) + == 0) { + *numBytes = fChars[deadKey[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[deadKey[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; +} + + +bool +BKeymap::operator==(const BKeymap& other) const +{ + return fCharsSize == other.fCharsSize + && !memcmp(&fKeys, &other.fKeys, sizeof(fKeys)) + && !memcmp(fChars, other.fChars, sizeof(fChars)); +} + + +bool +BKeymap::operator!=(const BKeymap& other) const +{ + return !(*this == other); +} + + +BKeymap& +BKeymap::operator=(const BKeymap& other) +{ + Unset(); + + fChars = new char[fCharsSize]; + fCharsSize = other.fCharsSize; + memcpy(fChars, other.fChars, fCharsSize); + memcpy(&fKeys, &other.fKeys, sizeof(fKeys)); + + return *this; +} + + +int32 +BKeymap::Offset(uint32 keyCode, uint32 modifiers, uint32* _table) const +{ + int32 offset; + uint32 table; + + if (keyCode >= 128) + return -1; + + switch (modifiers & kModifierKeys) { + case B_SHIFT_KEY: + offset = fKeys.shift_map[keyCode]; + table = B_SHIFT_TABLE; + break; + case B_CAPS_LOCK: + offset = fKeys.caps_map[keyCode]; + table = B_CAPS_TABLE; + break; + case B_CAPS_LOCK | B_SHIFT_KEY: + offset = fKeys.caps_shift_map[keyCode]; + table = B_CAPS_SHIFT_TABLE; + break; + case B_OPTION_KEY: + offset = fKeys.option_map[keyCode]; + table = B_OPTION_TABLE; + break; + case B_OPTION_KEY | B_SHIFT_KEY: + offset = fKeys.option_shift_map[keyCode]; + table = B_OPTION_SHIFT_TABLE; + break; + case B_OPTION_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_map[keyCode]; + table = B_OPTION_CAPS_TABLE; + break; + case B_OPTION_KEY | B_SHIFT_KEY | B_CAPS_LOCK: + offset = fKeys.option_caps_shift_map[keyCode]; + table = B_OPTION_CAPS_SHIFT_TABLE; + break; + case B_CONTROL_KEY: + offset = fKeys.control_map[keyCode]; + table = B_CONTROL_TABLE; + break; + default: + offset = fKeys.normal_map[keyCode]; + table = B_NORMAL_TABLE; + break; + } + + if (_table != NULL) + *_table = table; + + if (offset >= (int32)fCharsSize) + return -1; + + return offset; +} + + +uint8 +BKeymap::DeadKeyIndex(int32 offset) const +{ + if (fChars == NULL || offset <= 0) + return 0; + + uint32 numBytes = fChars[offset]; + if (!numBytes) + return 0; + + char chars[4]; + strncpy(chars, &fChars[offset + 1], numBytes); + chars[numBytes] = 0; + + const 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] + }; + + uint8 result = 0; + for (int32 i = 0; i < 5; i++) { + if (offset == deadOffsets[i]) { + result = i + 1; + break; + } + + uint32 deadNumBytes = fChars[deadOffsets[i]]; + if (!deadNumBytes) + continue; + + if (strncmp(chars, &fChars[deadOffsets[i] + 1], deadNumBytes) == 0) { + result = i + 1; + break; + } + } + + return result; +} diff --git a/src/preferences/keymap/Jamfile b/src/preferences/keymap/Jamfile index e3a1e6bdf1..5565e97e49 100644 --- a/src/preferences/keymap/Jamfile +++ b/src/preferences/keymap/Jamfile @@ -12,7 +12,7 @@ Preference Keymap : KeymapListItem.cpp KeymapWindow.cpp - : be tracker liblocale.so $(TARGET_LIBSTDC++) + : be tracker liblocale.so libshared.a $(TARGET_LIBSTDC++) : Keymap.rdef ; diff --git a/src/preferences/keymap/Keymap.cpp b/src/preferences/keymap/Keymap.cpp index 19cf7362b5..4d5aec1631 100644 --- a/src/preferences/keymap/Keymap.cpp +++ b/src/preferences/keymap/Keymap.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Haiku Inc. All rights reserved. + * Copyright 2004-2010 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -8,6 +8,7 @@ * Axel Dörfler, axeld@pinc-software.de. */ + #include "Keymap.h" #include @@ -61,8 +62,6 @@ print_key(char *chars, int32 offset) Keymap::Keymap() : - fChars(NULL), - fCharsSize(0), fModificationMessage(NULL) { } @@ -96,7 +95,8 @@ 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"); + printf("Key #\tNormal\tShift\tCaps\tC+S\tOption\tO+S\tO+C\tO+C+S\t" + "Control\n"); for (int i = 0; i < 128; i++) { printf(" 0x%x\t", i); print_key(fChars, fKeys.normal_map[i]); @@ -113,61 +113,29 @@ Keymap::DumpKeymap() } -/* - file format in big endian : - struct key_map - uint32 size of following charset - charset (offsets go into this with size of character followed by character) -*/ -// we load a map from a file +//! Load a map from a file status_t Keymap::Load(entry_ref &ref) { - status_t err; - BEntry entry(&ref, true); - if ((err = entry.InitCheck()) != B_OK) { - fprintf(stderr, "error loading keymap: %s\n", strerror(err)); - return err; - } + BEntry entry; + status_t status = entry.SetTo(&ref, true); + if (status != B_OK) + return status; BFile file(&entry, B_READ_ONLY); - if ((err = file.InitCheck()) != B_OK) { - fprintf(stderr, "error loading keymap: %s\n", strerror(err)); - return err; - } - - if ((err = file.Read(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys)) { - fprintf(stderr, "error reading keymap keys: %s\n", strerror(err)); - return B_BAD_VALUE; - } - - for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) - ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); - - if ((err = file.Read(&fCharsSize, sizeof(uint32))) < (ssize_t)sizeof(uint32)) { - fprintf(stderr, "error reading keymap size: %s\n", strerror(err)); - return B_BAD_VALUE; - } - - fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); - delete[] fChars; - - fChars = new char[fCharsSize]; - - ssize_t bytesRead = file.Read(fChars, fCharsSize); - if (bytesRead < 0) { - fprintf(stderr, "error reading keymap chars: %s\n", strerror(err)); - return (status_t)bytesRead; - } + status = SetTo(file); + if (status != B_OK) + return status; // fetch name from attribute and fall back to filename - bytesRead = file.ReadAttr("keymap:name", B_STRING_TYPE, 0, fName, + ssize_t bytesRead = file.ReadAttr("keymap:name", B_STRING_TYPE, 0, fName, sizeof(fName)); if (bytesRead > 0) fName[bytesRead] = '\0'; else strlcpy(fName, ref.name, sizeof(fName)); + return B_OK; } @@ -219,103 +187,6 @@ Keymap::Save(entry_ref& ref) } -bool -Keymap::Equals(const Keymap& other) const -{ - // not really efficient but this is the only way i found - // to reliably compare keymaps (used only for apply and revert) - return fCharsSize == other.fCharsSize - && !memcmp(&other.fKeys, &fKeys, sizeof(key_map)) - && !memcmp(other.fChars, fChars, fCharsSize); -} - - -/*! 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) -{ - return 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; -} - - -//! We need to know a modifier for a key -uint32 -Keymap::Modifier(uint32 keyCode) -{ - if (keyCode == fKeys.caps_key) - return B_CAPS_LOCK; - if (keyCode == fKeys.num_key) - return B_NUM_LOCK; - if (keyCode == fKeys.scroll_key) - return B_SCROLL_LOCK; - if (keyCode == fKeys.left_shift_key) - return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.right_shift_key) - return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.left_command_key) - return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.right_command_key) - return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.left_control_key) - return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.right_control_key) - return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.left_option_key) - return B_LEFT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.right_option_key) - return B_RIGHT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.menu_key) - return B_MENU_KEY; - - return 0; -} - - -uint32 -Keymap::KeyForModifier(uint32 modifier) -{ - if (modifier == B_CAPS_LOCK) - return fKeys.caps_key; - if (modifier == B_NUM_LOCK) - return fKeys.num_key; - if (modifier == B_SCROLL_LOCK) - return fKeys.scroll_key; - if (modifier == B_LEFT_SHIFT_KEY || modifier == B_SHIFT_KEY) - return fKeys.left_shift_key; - if (modifier == B_RIGHT_SHIFT_KEY) - return fKeys.right_shift_key; - if (modifier == B_LEFT_COMMAND_KEY || modifier == B_COMMAND_KEY) - return fKeys.left_command_key; - if (modifier == B_RIGHT_COMMAND_KEY) - return fKeys.right_command_key; - if (modifier == B_LEFT_CONTROL_KEY || modifier == B_CONTROL_KEY) - return fKeys.left_control_key; - if (modifier == B_RIGHT_CONTROL_KEY) - return fKeys.right_control_key; - if (modifier == B_LEFT_OPTION_KEY || modifier == B_OPTION_KEY) - return fKeys.left_option_key; - if (modifier == B_RIGHT_OPTION_KEY) - return fKeys.right_option_key; - if (modifier == B_MENU_KEY) - return fKeys.menu_key; - - return 0; -} - - status_t Keymap::SetModifier(uint32 keyCode, uint32 modifier) { @@ -362,81 +233,13 @@ Keymap::SetModifier(uint32 keyCode, uint32 modifier) } -/*! Checks whether a key is a dead key. - If it is, the enabled/disabled state of that dead key will be passed - out via isEnabled (isEnabled is not touched for non-dead keys). -*/ -uint8 -Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers, bool* isEnabled) -{ - uint32 tableMask = 0; - int32 offset = _Offset(keyCode, modifiers, &tableMask); - uint8 deadKeyIndex = _GetDeadKeyIndex(offset); - if (deadKeyIndex > 0 && isEnabled != NULL) { - uint32 deadTables[] = { - fKeys.acute_tables, - fKeys.grave_tables, - fKeys.circumflex_tables, - fKeys.dieresis_tables, - fKeys.tilde_tables - }; - *isEnabled = (deadTables[deadKeyIndex - 1] & tableMask) != 0; - } - - return deadKeyIndex; -} - - -//! 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 = _Offset(keyCode, modifiers); - if (offset < 0) - return false; - - 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; -} - - //! Enables/disables the "deadness" of the given keycode/modifier combo. void Keymap::SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers, bool enabled) { uint32 tableMask = 0; - int32 offset = _Offset(keyCode, modifiers, &tableMask); - uint8 deadKeyIndex = _GetDeadKeyIndex(offset); + int32 offset = Offset(keyCode, modifiers, &tableMask); + uint8 deadKeyIndex = DeadKeyIndex(offset); if (deadKeyIndex > 0) { uint32* deadTables[] = { &fKeys.acute_tables, @@ -529,105 +332,6 @@ Keymap::SetDeadKeyTrigger(dead_key_index deadKeyIndex, const BString& trigger) } -//! 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) -{ - *numBytes = 0; - *chars = NULL; - - if (keyCode > 128 || fChars == NULL) - return; - - // here we take NUMLOCK into account - if ((modifiers & B_NUM_LOCK) != 0) { - 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; - } - } - - int32 offset = _Offset(keyCode, modifiers); - if (offset < 0) - return; - - // here we get the char size - *numBytes = fChars[offset]; - if (!*numBytes) - return; - - // here we take an potential active dead key - int32 *deadKey; - switch (activeDeadKey) { - case kDeadKeyAcute: - deadKey = fKeys.acute_dead_key; - break; - case kDeadKeyGrave: - deadKey = fKeys.grave_dead_key; - break; - case kDeadKeyCircumflex: - deadKey = fKeys.circumflex_dead_key; - break; - case kDeadKeyDiaeresis: - deadKey = fKeys.dieresis_dead_key; - break; - case kDeadKeyTilde: - deadKey = 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[deadKey[i] + 1], *numBytes) - == 0) { - *numBytes = fChars[deadKey[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[deadKey[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; -} - - //! We make our input server use the map in /boot/home/config/settings/Keymap status_t Keymap::Use() @@ -640,7 +344,7 @@ void Keymap::SetKey(uint32 keyCode, uint32 modifiers, int8 deadKey, const char* bytes, int32 numBytes) { - int32 offset = _Offset(keyCode, modifiers); + int32 offset = Offset(keyCode, modifiers); if (offset < 0) return; @@ -684,64 +388,6 @@ Keymap::operator=(const Keymap& other) } -int32 -Keymap::_Offset(uint32 keyCode, uint32 modifiers, uint32* _table) -{ - int32 offset; - uint32 table; - - if (keyCode >= 128) - return -1; - - switch (modifiers & kModifierKeys) { - case B_SHIFT_KEY: - offset = fKeys.shift_map[keyCode]; - table = B_SHIFT_TABLE; - break; - case B_CAPS_LOCK: - offset = fKeys.caps_map[keyCode]; - table = B_CAPS_TABLE; - break; - case B_CAPS_LOCK | B_SHIFT_KEY: - offset = fKeys.caps_shift_map[keyCode]; - table = B_CAPS_SHIFT_TABLE; - break; - case B_OPTION_KEY: - offset = fKeys.option_map[keyCode]; - table = B_OPTION_TABLE; - break; - case B_OPTION_KEY | B_SHIFT_KEY: - offset = fKeys.option_shift_map[keyCode]; - table = B_OPTION_SHIFT_TABLE; - break; - case B_OPTION_KEY | B_CAPS_LOCK: - offset = fKeys.option_caps_map[keyCode]; - table = B_OPTION_CAPS_TABLE; - break; - case B_OPTION_KEY | B_SHIFT_KEY | B_CAPS_LOCK: - offset = fKeys.option_caps_shift_map[keyCode]; - table = B_OPTION_CAPS_SHIFT_TABLE; - break; - case B_CONTROL_KEY: - offset = fKeys.control_map[keyCode]; - table = B_CONTROL_TABLE; - break; - default: - offset = fKeys.normal_map[keyCode]; - table = B_NORMAL_TABLE; - break; - } - - if (_table != NULL) - *_table = table; - - if (offset >= (int32)fCharsSize) - return -1; - - return offset; -} - - bool Keymap::_SetChars(int32 offset, const char* bytes, int32 numBytes) { @@ -790,46 +436,3 @@ Keymap::_SetChars(int32 offset, const char* bytes, int32 numBytes) return true; } - - -uint8 -Keymap::_GetDeadKeyIndex(int32 offset) -{ - if (fChars == NULL || 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] - }; - - uint8 result = 0; - for (int32 i = 0; i < 5; i++) { - if (offset == deadOffsets[i]) { - result = i + 1; - break; - } - - uint32 deadNumBytes = fChars[deadOffsets[i]]; - if (!deadNumBytes) - continue; - - if (strncmp(chars, &fChars[deadOffsets[i] + 1], deadNumBytes) == 0) { - result = i + 1; - break; - } - } - - return result; -} diff --git a/src/preferences/keymap/Keymap.h b/src/preferences/keymap/Keymap.h index 659d590d3b..0d6ee3aa25 100644 --- a/src/preferences/keymap/Keymap.h +++ b/src/preferences/keymap/Keymap.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Haiku Inc. All rights reserved. + * Copyright 2004-2010 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -10,7 +10,8 @@ #define KEYMAP_H -#include +#include + #include #include #include @@ -25,7 +26,7 @@ enum dead_key_index { }; -class Keymap { +class Keymap : public BKeymap { public: Keymap(); ~Keymap(); @@ -38,15 +39,8 @@ public: void DumpKeymap(); - bool IsModifierKey(uint32 keyCode); - uint32 Modifier(uint32 keyCode); - uint32 KeyForModifier(uint32 modifier); status_t SetModifier(uint32 keyCode, uint32 modifier); - uint8 IsDeadKey(uint32 keyCode, uint32 modifiers, - bool* isEnabled = NULL); - bool IsDeadSecondKey(uint32 keyCode, uint32 modifiers, - uint8 activeDeadKey); void SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers, bool enabled); void GetDeadKeyTrigger(dead_key_index deadKeyIndex, @@ -54,11 +48,7 @@ public: void SetDeadKeyTrigger(dead_key_index deadKeyIndex, const BString& trigger); - void GetChars(uint32 keyCode, uint32 modifiers, - uint8 activeDeadKey, char** chars, - int32* numBytes); status_t Use(); - bool Equals(const Keymap& map) const; void SetKey(uint32 keyCode, uint32 modifiers, int8 deadKey, const char* bytes, @@ -72,15 +62,10 @@ public: Keymap& operator=(const Keymap& other); private: - int32 _Offset(uint32 keyCode, uint32 modifiers, - uint32* _table = NULL); bool _SetChars(int32 offset, const char* bytes, int32 numBytes); - uint8 _GetDeadKeyIndex(int32 offset); - char* fChars; - key_map fKeys; - uint32 fCharsSize; +private: char fName[B_FILE_NAME_LENGTH]; BMessenger fTarget; diff --git a/src/preferences/keymap/KeymapWindow.cpp b/src/preferences/keymap/KeymapWindow.cpp index 5934a34516..5041daf5f6 100644 --- a/src/preferences/keymap/KeymapWindow.cpp +++ b/src/preferences/keymap/KeymapWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Haiku Inc. All rights reserved. + * Copyright 2004-2010 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -647,12 +647,12 @@ KeymapWindow::_UpdateDeadKeyMenu() void KeymapWindow::_UpdateButtons() { - if (!fCurrentMap.Equals(fAppliedMap)) { + if (fCurrentMap != fAppliedMap) { fCurrentMap.SetName(kCurrentKeymapName); _UseKeymap(); } - fRevertButton->SetEnabled(!fCurrentMap.Equals(fPreviousMap)); + fRevertButton->SetEnabled(fCurrentMap != fPreviousMap); _UpdateDeadKeyMenu(); _UpdateSwitchShortcutButton();