1/* 2 * Copyright 1999-2009 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jeremy Friesner 7 */ 8 9 10#include "KeyInfos.h" 11 12#include <ctype.h> 13#include <sstream> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string> 17#include <strings.h> 18 19#include <InterfaceDefs.h> 20 21 22#define NUM_KEYS 128 23#define MAX_UTF8_LENGTH 5 24 // up to 4 chars, plus a \0 terminator 25 26 27struct KeyLabelMap { 28 const char* fLabel; 29 uint8 fKeyCode; 30}; 31 32 33// This is a table of keys-codes that have special, hard-coded labels. 34static const struct KeyLabelMap keyLabels[] = { 35 {"<unset>", 0}, 36 {"Esc", 1}, 37 {"F1", 2}, 38 {"F2", 3}, 39 {"F3", 4}, 40 {"F4", 5}, 41 {"F5", 6}, 42 {"F6", 7}, 43 {"F7", 8}, 44 {"F8", 9}, 45 {"F9", 10}, 46 {"F10", 11}, 47 {"F11", 12}, 48 {"F12", 13}, 49 {"SysRq", 14}, 50 {"ScrlLck", 15}, 51 {"Pause", 16}, 52 {"Bcksp", 30}, 53 {"Insert", 31}, 54 {"Home", 32}, 55 {"PgUp", 33}, 56 {"Num Lock", 34}, 57 {"Kpd /", 35}, 58 {"Kpd *", 36}, 59 {"Kpd -", 37}, 60 {"Tab", 38}, 61 {"Delete", 52}, 62 {"End", 53}, 63 {"PgDn", 54}, 64 {"Kpd 7", 55}, 65 {"Kpd 8", 56}, 66 {"Kpd 9", 57}, 67 {"Kpd +", 58}, 68 {"Caps Lock", 59}, 69 {"Enter", 71}, 70 {"Kpd 4", 72}, 71 {"Kpd 5", 73}, 72 {"Kpd 6", 74}, 73 {"L.Shift", 75}, 74 {"R.Shift", 86}, 75 {"Up", 87}, 76 {"Kpd 1", 88}, 77 {"Kpd 2", 89}, 78 {"Kpd 3", 90}, 79 {"Kpd Entr", 91}, 80 {"L.Control", 92}, 81 {"L.Alt", 93}, 82 {"Space", 94}, 83 {"R.Alt", 95}, 84 {"R.Control", 96}, 85 {"Left", 97}, 86 {"Down", 98}, 87 {"Right", 99}, 88 {"Kpd 0", 100}, 89 {"Kpd .", 101}, 90 {"L.Command", 102}, 91 {"R.Command", 103}, 92 {"Menu", 104}, 93 {"PowerOn", 107}, 94}; 95 96 97// Key description strings (e.g. "A" or "Escape"). NULL if no description is 98// available. 99static const char* keyDescriptions[NUM_KEYS]; 100 101 102// series of optional up-to-(4+1)-byte terminated UTF-8 character strings... 103static char utfDescriptions[NUM_KEYS * MAX_UTF8_LENGTH]; 104 105 106static const char* 107FindSpecialKeyLabelFor(uint8 keyCode, uint32& last) 108{ 109 while ((keyLabels[last].fKeyCode < keyCode) 110 && (last < (sizeof(keyLabels) / sizeof(struct KeyLabelMap)) - 1)) { 111 last++; 112 } 113 114 if (keyLabels[last].fKeyCode == keyCode) 115 return keyLabels[last].fLabel; 116 else 117 return NULL; 118} 119 120 121void 122InitKeyIndices() 123{ 124 uint32 nextSpecial = 0; 125 key_map* map; 126 char* keys; 127 get_key_map(&map, &keys); 128 129 if (map == NULL || keys == NULL) 130 return; 131 132 for (uint8 j = 0; j < NUM_KEYS; j++) { 133 keyDescriptions[j] = NULL; 134 // default 135 136 const char* specialLabel = FindSpecialKeyLabelFor(j, nextSpecial); 137 int32 keyCode = map->normal_map[j]; 138 139 if (keyCode >= 0) { 140 const char* mapDesc = &keys[keyCode]; 141 uint8 length = *mapDesc; 142 143 for (int m = 0; m < MAX_UTF8_LENGTH; m++) 144 if (m < length) 145 utfDescriptions[j * MAX_UTF8_LENGTH + m] = mapDesc[m + 1]; 146 else 147 utfDescriptions[j * MAX_UTF8_LENGTH + m] = '\0'; 148 149 if (specialLabel != NULL) 150 keyDescriptions[j] = specialLabel; 151 else { 152 // If it's an ASCII letter, capitalize it. 153 char& c = utfDescriptions[j * MAX_UTF8_LENGTH]; 154 155 if ((length == 1) && (isalpha(c))) 156 c = toupper(c); 157 158 if (length > 1 || (length == 1 && c > ' ')) 159 keyDescriptions[j] = &c; 160 } 161 } else 162 utfDescriptions[j * MAX_UTF8_LENGTH] = 0x00; 163 } 164 165 free(keys); 166 free(map); 167} 168 169 170const char* 171GetKeyUTF8(uint8 keyIndex) 172{ 173 return &utfDescriptions[keyIndex * MAX_UTF8_LENGTH]; 174} 175 176 177const char* 178GetKeyName(uint32 keyIndex) 179{ 180 if (keyIndex >= NUM_KEYS) 181 return NULL; 182 return keyDescriptions[keyIndex]; 183} 184 185 186BString 187GetFallbackKeyName(uint32 keyCode) 188{ 189 BString keyCodeName = "KeyCode "; 190 std::stringstream sstream; 191 sstream << std::hex << keyCode; 192 keyCodeName.Append(sstream.str().c_str()); 193 return keyCodeName; 194} 195 196 197int 198GetNumKeyIndices() 199{ 200 return NUM_KEYS; 201} 202 203 204uint32 205FindKeyCode(const char* keyName) 206{ 207 if (strncmp(keyName, "KeyCode ", 7) == 0) 208 return strtoul(keyName + 7, NULL, 16); 209 210 for (uint8 i = 0; i < NUM_KEYS; i++) { 211 if ((keyDescriptions[i]) 212 && (strcasecmp(keyName, keyDescriptions[i]) == 0)) { 213 return i; 214 } 215 } 216 217 return 0; 218 // default to sentinel value 219} 220