1 /* 2 * Copyright 2004-2006, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval 7 */ 8 9 10 #include "Keymap.h" 11 12 #include <ByteOrder.h> 13 #include <File.h> 14 15 #include <new> 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 21 static void 22 print_key(char *chars, int32 offset) 23 { 24 int size = chars[offset++]; 25 26 switch (size) { 27 case 0: 28 // Not mapped 29 printf("N/A"); 30 break; 31 32 case 1: 33 // 1-byte UTF-8/ASCII character 34 printf("%c", chars[offset]); 35 break; 36 37 default: 38 { 39 // 2-, 3-, or 4-byte UTF-8 character 40 char *str = new (std::nothrow) char[size + 1]; 41 if (str == NULL) 42 break; 43 44 strncpy(str, &(chars[offset]), size); 45 str[size] = 0; 46 printf("%s", str); 47 delete [] str; 48 break; 49 } 50 } 51 52 printf("\t"); 53 } 54 55 56 // #pragma mark - 57 58 59 void 60 Keymap::DumpKeymap() 61 { 62 // Print a chart of the normal, shift, option, and option+shift 63 // keys. 64 printf("Key #\tNormal\tShift\tCaps\tC+S\tOption\tO+S\tO+C\tO+C+S\tControl\n"); 65 66 for (int i = 0; i < 128; i++) { 67 printf(" 0x%x\t", i); 68 print_key(fChars, fKeys.normal_map[i]); 69 print_key(fChars, fKeys.shift_map[i]); 70 print_key(fChars, fKeys.caps_map[i]); 71 print_key(fChars, fKeys.caps_shift_map[i]); 72 print_key(fChars, fKeys.option_map[i]); 73 print_key(fChars, fKeys.option_shift_map[i]); 74 print_key(fChars, fKeys.option_caps_map[i]); 75 print_key(fChars, fKeys.option_caps_shift_map[i]); 76 print_key(fChars, fKeys.control_map[i]); 77 printf("\n"); 78 } 79 } 80 81 82 Keymap::Keymap() 83 : 84 fChars(NULL) 85 { 86 key_map *keys; 87 get_key_map(&keys, &fChars); 88 89 if (keys) { 90 memcpy(&fKeys, keys, sizeof(key_map)); 91 free(keys); 92 } 93 } 94 95 96 Keymap::~Keymap() 97 { 98 free(fChars); 99 } 100 101 102 /* we need to know if a key is a modifier key to choose 103 a valid key when several are pressed together 104 */ 105 bool 106 Keymap::IsModifierKey(uint32 keyCode) 107 { 108 return keyCode == fKeys.caps_key 109 || keyCode == fKeys.num_key 110 || keyCode == fKeys.scroll_key 111 || keyCode == fKeys.left_shift_key 112 || keyCode == fKeys.right_shift_key 113 || keyCode == fKeys.left_command_key 114 || keyCode == fKeys.right_command_key 115 || keyCode == fKeys.left_control_key 116 || keyCode == fKeys.right_control_key 117 || keyCode == fKeys.left_option_key 118 || keyCode == fKeys.right_option_key 119 || keyCode == fKeys.menu_key; 120 } 121 122 123 //! We need to know a modifier for a key 124 uint32 125 Keymap::Modifier(uint32 keyCode) 126 { 127 if (keyCode == fKeys.caps_key) 128 return B_CAPS_LOCK; 129 if (keyCode == fKeys.num_key) 130 return B_NUM_LOCK; 131 if (keyCode == fKeys.scroll_key) 132 return B_SCROLL_LOCK; 133 if (keyCode == fKeys.left_shift_key) 134 return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; 135 if (keyCode == fKeys.right_shift_key) 136 return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; 137 if (keyCode == fKeys.left_command_key) 138 return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; 139 if (keyCode == fKeys.right_command_key) 140 return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; 141 if (keyCode == fKeys.left_control_key) 142 return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; 143 if (keyCode == fKeys.right_control_key) 144 return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; 145 if (keyCode == fKeys.left_option_key) 146 return B_LEFT_OPTION_KEY | B_OPTION_KEY; 147 if (keyCode == fKeys.right_option_key) 148 return B_RIGHT_OPTION_KEY | B_OPTION_KEY; 149 if (keyCode == fKeys.menu_key) 150 return B_MENU_KEY; 151 152 return 0; 153 } 154 155 156 //! Tell if a key is a dead key, needed for draw a dead key 157 uint8 158 Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) 159 { 160 if (keyCode >= 256) 161 return 0; 162 163 int32 offset; 164 uint32 tableMask = 0; 165 166 switch (modifiers & 0xcf) { 167 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; tableMask = B_SHIFT_TABLE; break; 168 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; tableMask = B_CAPS_TABLE; break; 169 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; tableMask = B_CAPS_SHIFT_TABLE; break; 170 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; tableMask = B_OPTION_TABLE; break; 171 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; tableMask = B_OPTION_SHIFT_TABLE; break; 172 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; tableMask = B_OPTION_CAPS_TABLE; break; 173 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; tableMask = B_OPTION_CAPS_SHIFT_TABLE; break; 174 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; tableMask = B_CONTROL_TABLE; break; 175 default: offset = fKeys.normal_map[keyCode]; tableMask = B_NORMAL_TABLE; break; 176 } 177 178 if (offset <= 0) 179 return 0; 180 181 uint32 numBytes = fChars[offset]; 182 if (!numBytes) 183 return 0; 184 185 char chars[4]; 186 strncpy(chars, &(fChars[offset+1]), numBytes ); 187 chars[numBytes] = 0; 188 189 int32 deadOffsets[] = { 190 fKeys.acute_dead_key[1], 191 fKeys.grave_dead_key[1], 192 fKeys.circumflex_dead_key[1], 193 fKeys.dieresis_dead_key[1], 194 fKeys.tilde_dead_key[1] 195 }; 196 197 uint32 deadTables[] = { 198 fKeys.acute_tables, 199 fKeys.grave_tables, 200 fKeys.circumflex_tables, 201 fKeys.dieresis_tables, 202 fKeys.tilde_tables 203 }; 204 205 for (int32 i = 0; i < 5; i++) { 206 if ((deadTables[i] & tableMask) == 0) 207 continue; 208 209 if (offset == deadOffsets[i]) 210 return i + 1; 211 212 uint32 deadNumBytes = fChars[deadOffsets[i]]; 213 if (!deadNumBytes) 214 continue; 215 216 if (!strncmp(chars, &(fChars[deadOffsets[i] + 1]), deadNumBytes)) 217 return i + 1; 218 } 219 return 0; 220 } 221 222 223 //! Tell if a key is a dead second key, needed for draw a dead second key 224 bool 225 Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) 226 { 227 if (!activeDeadKey || keyCode >= 256) 228 return false; 229 230 int32 offset; 231 232 switch (modifiers & 0xcf) { 233 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; 234 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; 235 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; 236 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; 237 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; 238 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; 239 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; 240 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; 241 default: offset = fKeys.normal_map[keyCode]; break; 242 } 243 244 if (offset <= 0) 245 return false; 246 247 uint32 numBytes = fChars[offset]; 248 if (!numBytes) 249 return false; 250 251 int32* deadOffsets[] = { 252 fKeys.acute_dead_key, 253 fKeys.grave_dead_key, 254 fKeys.circumflex_dead_key, 255 fKeys.dieresis_dead_key, 256 fKeys.tilde_dead_key 257 }; 258 259 int32 *deadOffset = deadOffsets[activeDeadKey-1]; 260 261 for (int32 i=0; i<32; i++) { 262 if (offset == deadOffset[i]) 263 return true; 264 265 uint32 deadNumBytes = fChars[deadOffset[i]]; 266 if (!deadNumBytes) 267 continue; 268 269 if (!strncmp(&(fChars[offset+1]), &(fChars[deadOffset[i]+1]), deadNumBytes)) 270 return true; 271 272 i++; 273 } 274 275 return false; 276 } 277 278 279 //! Get the char for a key given modifiers and active dead key 280 void 281 Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, 282 char** chars, int32* numBytes) 283 { 284 *numBytes = 0; 285 *chars = NULL; 286 287 if (keyCode >= 256) 288 return; 289 290 // here we take NUMLOCK into account 291 if (modifiers & B_NUM_LOCK) { 292 switch (keyCode) { 293 case 0x37: 294 case 0x38: 295 case 0x39: 296 case 0x48: 297 case 0x49: 298 case 0x4a: 299 case 0x58: 300 case 0x59: 301 case 0x5a: 302 case 0x64: 303 case 0x65: 304 modifiers ^= B_SHIFT_KEY; 305 break; 306 } 307 } 308 309 int32 offset; 310 311 // here we choose the right map given the modifiers 312 switch (modifiers & 0xcf) { 313 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; 314 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; 315 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; 316 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; 317 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; 318 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; 319 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; 320 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; 321 322 default: 323 offset = fKeys.normal_map[keyCode]; 324 break; 325 } 326 327 if (offset <= 0) 328 return; 329 330 // here we get the char size 331 *numBytes = fChars[offset]; 332 if (!*numBytes) 333 return; 334 335 // here we take an potential active dead key 336 int32 *deadKey; 337 switch (activeDeadKey) { 338 case 1: deadKey = fKeys.acute_dead_key; break; 339 case 2: deadKey = fKeys.grave_dead_key; break; 340 case 3: deadKey = fKeys.circumflex_dead_key; break; 341 case 4: deadKey = fKeys.dieresis_dead_key; break; 342 case 5: deadKey = fKeys.tilde_dead_key; break; 343 default: 344 { 345 // if not dead, we copy and return the char 346 char *str = *chars = new (std::nothrow) char[*numBytes + 1]; 347 if (str == NULL) { 348 *numBytes = 0; 349 return; 350 } 351 strncpy(str, &(fChars[offset + 1]), *numBytes); 352 str[*numBytes] = 0; 353 return; 354 } 355 } 356 357 // if dead key, we search for our current offset char in the dead key offset table 358 // string comparison is needed 359 for (int32 i = 0; i < 32; i++) { 360 if (strncmp(&(fChars[offset + 1]), &(fChars[deadKey[i] + 1]), *numBytes) == 0) { 361 *numBytes = fChars[deadKey[i + 1]]; 362 363 switch (*numBytes) { 364 case 0: 365 // Not mapped 366 *chars = NULL; 367 break; 368 default: 369 { 370 // 1-, 2-, 3-, or 4-byte UTF-8 character 371 char *str = *chars = new (std::nothrow) char[*numBytes + 1]; 372 if (str == NULL) { 373 *numBytes = 0; 374 return; 375 } 376 strncpy(str, &fChars[deadKey[i + 1] + 1], *numBytes); 377 str[*numBytes] = 0; 378 break; 379 } 380 } 381 return; 382 } 383 i++; 384 } 385 386 // if not found we return the current char mapped 387 *chars = new (std::nothrow) char[*numBytes + 1]; 388 if (*chars == NULL) { 389 *numBytes = 0; 390 return; 391 } 392 393 strncpy(*chars, &(fChars[offset+1]), *numBytes ); 394 (*chars)[*numBytes] = 0; 395 } 396 397 398 status_t 399 Keymap::LoadCurrent() 400 { 401 key_map *keys = NULL; 402 free(fChars); 403 fChars = NULL; 404 405 get_key_map(&keys, &fChars); 406 if (!keys) { 407 fprintf(stderr, "error while getting current keymap!\n"); 408 return B_ERROR; 409 } 410 memcpy(&fKeys, keys, sizeof(fKeys)); 411 free(keys); 412 return B_OK; 413 } 414 415