1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 2 // 3 // Copyright (c) 2004, Haiku 4 // 5 // This software is part of the Haiku distribution and is covered 6 // by the Haiku license. 7 // 8 // 9 // File: Keymap.cpp 10 // Author: Jérôme Duval 11 // Description: keymap bin 12 // Created : July 29, 2004 13 // 14 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 15 16 #include "Keymap.h" 17 #include <stdlib.h> 18 #include <string.h> 19 #include <regex.h> 20 #include <ByteOrder.h> 21 #include <File.h> 22 #include <FindDirectory.h> 23 #include <Path.h> 24 #include <String.h> 25 26 #define CHARS_TABLE_MAXSIZE 10000 27 28 Keymap::Keymap() 29 : fChars(NULL), 30 fCharsSize(0) 31 { 32 } 33 34 35 Keymap::~Keymap() 36 { 37 if (fChars) 38 free(fChars); 39 } 40 41 42 void 43 Keymap::GetKey( char *chars, int32 offset, char* string) 44 { 45 int size = chars[offset++]; 46 char str[32]; 47 memset(str, 0, 32); 48 memset(string, 0, 32); 49 50 switch( size ) { 51 case 0: 52 // Not mapped 53 sprintf(str, "''"); 54 break; 55 56 case 1: 57 // 1-byte UTF-8/ASCII character 58 if ((uint8)chars[offset] < 0x20 59 || (uint8)chars[offset] > 0x7e) 60 sprintf(str, "0x%02x", (uint8)chars[offset]); 61 else 62 sprintf(str, "'%s%c'", 63 (chars[offset] == '\\' || chars[offset] == '\'') ? "\\" : "", chars[offset]); 64 break; 65 66 default: 67 // n-byte UTF-8/ASCII character 68 sprintf(str, "0x"); 69 for (int i=0; i<size; i++) 70 sprintf(str + 2*(i+1), "%02x", (uint8)chars[offset+i]); 71 break; 72 } 73 strncpy(string, str, (strlen(str) < 12) ? strlen(str) : 12); 74 } 75 76 77 void 78 Keymap::Dump() 79 { 80 printf( 81 "#!/bin/keymap -l\n" 82 "#\n" 83 "#\tRaw key numbering for 101 keyboard...\n" 84 "# [sys] [brk]\n" 85 "# 0x7e 0x7f\n" 86 "# [esc] [ f1] [ f2] [ f3] [ f4] [ f5] [ f6] [ f7] [ f8] [ f9] [f10] [f11] [f12] [prn] [scr] [pau]\n" 87 "# 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 K E Y P A D K E Y S\n" 88 "#\n" 89 "# [ ` ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ] [ - ] [ = ] [bck] [ins] [hme] [pup] [num] [ / ] [ * ] [ - ]\n" 90 "# 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25\n" 91 "#\n" 92 "# [tab] [ q ] [ w ] [ e ] [ r ] [ t ] [ y ] [ u ] [ i ] [ o ] [ p ] [ [ ] [ ] ] [ \\ ] [del] [end] [pdn] [ 7 ] [ 8 ] [ 9 ] [ + ]\n" 93 "# 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a\n" 94 "#\n" 95 "# [cap] [ a ] [ s ] [ d ] [ f ] [ g ] [ h ] [ j ] [ k ] [ l ] [ ; ] [ ' ] [ enter ] [ 4 ] [ 5 ] [ 6 ]\n" 96 "# 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a\n" 97 "#\n" 98 "# [shift] [ z ] [ x ] [ c ] [ v ] [ b ] [ n ] [ m ] [ , ] [ . ] [ / ] [shift] [ up] [ 1 ] [ 2 ] [ 3 ] [ent]\n" 99 "# 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b\n" 100 "#\n" 101 "# [ctr] [cmd] [ space ] [cmd] [ctr] [lft] [dwn] [rgt] [ 0 ] [ . ]\n" 102 "# 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65\n" 103 "#\n" 104 "#\tNOTE: On a Microsoft Natural Keyboard:\n" 105 "#\t\t\tleft option = 0x66\n" 106 "#\t\t\tright option = 0x67\n" 107 "#\t\t\tmenu key = 0x68\n" 108 "#\tNOTE: On an Apple Extended Keyboard:\n" 109 "#\t\t\tleft option = 0x66\n" 110 "#\t\t\tright option = 0x67\n" 111 "#\t\t\tkeypad '=' = 0x6a\n" 112 "#\t\t\tpower key = 0x6b\n"); 113 114 printf("Version = %ld\n", fKeys.version); 115 printf("CapsLock = 0x%02lx\n", fKeys.caps_key); 116 printf("ScrollLock = 0x%02lx\n", fKeys.scroll_key); 117 printf("NumLock = 0x%02lx\n", fKeys.num_key); 118 printf("LShift = 0x%02lx\n", fKeys.left_shift_key); 119 printf("RShift = 0x%02lx\n", fKeys.right_shift_key); 120 printf("LCommand = 0x%02lx\n", fKeys.left_command_key); 121 printf("RCommand = 0x%02lx\n", fKeys.right_command_key); 122 printf("LControl = 0x%02lx\n", fKeys.left_control_key); 123 printf("RControl = 0x%02lx\n", fKeys.right_control_key); 124 printf("LOption = 0x%02lx\n", fKeys.left_option_key); 125 printf("ROption = 0x%02lx\n", fKeys.right_option_key); 126 printf("Menu = 0x%02lx\n", fKeys.menu_key); 127 printf( 128 "#\n" 129 "# Lock settings\n" 130 "# To set NumLock, do the following:\n" 131 "# LockSettings = NumLock\n" 132 "#\n" 133 "# To set everything, do the following:\n" 134 "# LockSettings = CapsLock NumLock ScrollLock\n" 135 "#\n"); 136 printf("LockSettings = "); 137 if (fKeys.lock_settings & B_CAPS_LOCK) 138 printf("CapsLock "); 139 if (fKeys.lock_settings & B_NUM_LOCK) 140 printf("NumLock "); 141 if (fKeys.lock_settings & B_SCROLL_LOCK) 142 printf("ScrollLock "); 143 printf("\n"); 144 printf( 145 "# Legend:\n" 146 "# n = Normal\n" 147 "# s = Shift\n" 148 "# c = Control\n" 149 "# C = CapsLock\n" 150 "# o = Option\n" 151 "# Key n s c o os C Cs Co Cos \n"); 152 153 for( int idx = 0; idx < 128; idx++ ) { 154 char normalKey[32]; 155 char shiftKey[32]; 156 char controlKey[32]; 157 char optionKey[32]; 158 char optionShiftKey[32]; 159 char capsKey[32]; 160 char capsShiftKey[32]; 161 char optionCapsKey[32]; 162 char optionCapsShiftKey[32]; 163 164 GetKey( fChars, fKeys.normal_map[idx], normalKey); 165 GetKey( fChars, fKeys.shift_map[idx], shiftKey); 166 GetKey( fChars, fKeys.control_map[idx], controlKey); 167 GetKey( fChars, fKeys.option_map[idx], optionKey); 168 GetKey( fChars, fKeys.option_shift_map[idx], optionShiftKey); 169 GetKey( fChars, fKeys.caps_map[idx], capsKey); 170 GetKey( fChars, fKeys.caps_shift_map[idx], capsShiftKey); 171 GetKey( fChars, fKeys.option_caps_map[idx], optionCapsKey); 172 GetKey( fChars, fKeys.option_caps_shift_map[idx], optionCapsShiftKey); 173 174 printf("Key 0x%02x = %-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s%-9s\n", idx, normalKey, shiftKey, controlKey, 175 optionKey, optionShiftKey, capsKey, capsShiftKey, optionCapsKey, optionCapsShiftKey); 176 } 177 178 int32* deadOffsets[] = { 179 fKeys.acute_dead_key, 180 fKeys.grave_dead_key, 181 fKeys.circumflex_dead_key, 182 fKeys.dieresis_dead_key, 183 fKeys.tilde_dead_key 184 }; 185 186 char labels[][12] = { 187 "Acute", 188 "Grave", 189 "Circumflex", 190 "Diaeresis", 191 "Tilde" 192 }; 193 194 uint32 deadTables[] = { 195 fKeys.acute_tables, 196 fKeys.grave_tables, 197 fKeys.circumflex_tables, 198 fKeys.dieresis_tables, 199 fKeys.tilde_tables 200 }; 201 202 for (int i = 0; i<5; i++) { 203 for (int idx = 0; idx < 32; idx++ ) { 204 char deadKey[32]; 205 char secondKey[32]; 206 GetKey( fChars, deadOffsets[i][idx++], deadKey); 207 GetKey( fChars, deadOffsets[i][idx], secondKey); 208 printf("%s %-9s = %-9s\n", labels[i], deadKey, secondKey); 209 } 210 211 printf("%sTab = ", labels[i]); 212 213 if (deadTables[i] & B_NORMAL_TABLE) 214 printf("Normal "); 215 if (deadTables[i] & B_SHIFT_TABLE) 216 printf("Shift "); 217 if (deadTables[i] & B_CONTROL_TABLE) 218 printf("Control "); 219 if (deadTables[i] & B_OPTION_TABLE) 220 printf("Option "); 221 if (deadTables[i] & B_OPTION_SHIFT_TABLE) 222 printf("Option-Shift "); 223 if (deadTables[i] & B_CAPS_TABLE) 224 printf("CapsLock "); 225 if (deadTables[i] & B_CAPS_SHIFT_TABLE) 226 printf("CapsLock-Shift "); 227 if (deadTables[i] & B_OPTION_CAPS_TABLE) 228 printf("CapsLock-Option "); 229 if (deadTables[i] & B_OPTION_CAPS_SHIFT_TABLE) 230 printf("CapsLock-Option-Shift "); 231 printf("\n"); 232 } 233 234 } 235 236 237 status_t 238 Keymap::LoadCurrent() 239 { 240 #ifdef __BEOS__ 241 242 key_map *keys = NULL; 243 get_key_map(&keys, &fChars); 244 if (!keys) { 245 fprintf(stderr, "error while getting current keymap!\n"); 246 return B_ERROR; 247 } 248 memcpy(&fKeys, keys, sizeof(fKeys)); 249 free(keys); 250 return B_OK; 251 252 #else // ! __BEOS__ 253 fprintf(stderr, "Unsupported operation on this platform!\n"); 254 exit(1); 255 #endif // ! __BEOS__ 256 } 257 258 /* 259 file format in big endian : 260 struct key_map 261 uint32 size of following charset 262 charset (offsets go into this with size of character followed by character) 263 */ 264 // we load a map from a file 265 status_t 266 Keymap::Load(entry_ref &ref) 267 { 268 status_t err; 269 270 BFile file(&ref, B_READ_ONLY); 271 if ((err = file.InitCheck()) != B_OK) { 272 printf("error %s\n", strerror(err)); 273 return err; 274 } 275 276 if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys)) { 277 return B_BAD_VALUE; 278 } 279 280 for (uint32 i=0; i<sizeof(fKeys)/4; i++) 281 ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); 282 283 if (fKeys.version != 3) 284 return B_ERROR; 285 286 if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32)) { 287 return B_BAD_VALUE; 288 } 289 290 fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); 291 if (!fChars) 292 delete[] fChars; 293 fChars = new char[fCharsSize]; 294 if ((unsigned)file.Read(fChars, fCharsSize) != fCharsSize) 295 return B_BAD_VALUE; 296 297 return B_OK; 298 } 299 300 301 void 302 Keymap::ComputeChars(const char *buffer, struct re_registers ®s, int i, int &offset) 303 { 304 char *current = &fChars[offset + 1]; 305 char hexChars[12]; 306 uint32 length = 0; 307 if (strncmp(buffer + regs.start[i], "''", regs.end[i] - regs.start[i]) == 0) 308 length = 0; 309 else if (sscanf(buffer + regs.start[i], "'%s'", current) > 0) { 310 if (current[0] == '\\') 311 current[0] = current[1]; 312 else if (current[0] == '\'') 313 current[0] = ' '; 314 length = 1; 315 } else if (sscanf(buffer + regs.start[i], "0x%s", hexChars) > 0) { 316 length = strlen(hexChars) / 2; 317 for (uint32 j = 0; j < length; j++) 318 sscanf(hexChars + 2*j, "%02hhx", current + j); 319 } 320 fChars[offset] = length; 321 offset += length + 1; 322 } 323 324 325 void 326 Keymap::ComputeTables(const char *buffer, struct re_registers ®s, uint32 &table) 327 { 328 for (int32 i=1; i<=9; i++) { 329 if (regs.end[i] - regs.start[i] <= 0) 330 break; 331 if (strncmp(buffer + regs.start[i], "Normal", regs.end[i] - regs.start[i]) == 0) 332 table |= B_NORMAL_TABLE; 333 else if (strncmp(buffer + regs.start[i], "Shift", regs.end[i] - regs.start[i]) == 0) 334 table |= B_SHIFT_TABLE; 335 else if (strncmp(buffer + regs.start[i], "Control", regs.end[i] - regs.start[i]) == 0) 336 table |= B_CONTROL_TABLE; 337 else if (strncmp(buffer + regs.start[i], "Option", regs.end[i] - regs.start[i]) == 0) 338 table |= B_OPTION_TABLE; 339 else if (strncmp(buffer + regs.start[i], "Option-Shift", regs.end[i] - regs.start[i]) == 0) 340 table |= B_OPTION_SHIFT_TABLE; 341 else if (strncmp(buffer + regs.start[i], "CapsLock", regs.end[i] - regs.start[i]) == 0) 342 table |= B_CAPS_TABLE; 343 else if (strncmp(buffer + regs.start[i], "CapsLock-Shift", regs.end[i] - regs.start[i]) == 0) 344 table |= B_CAPS_SHIFT_TABLE; 345 else if (strncmp(buffer + regs.start[i], "CapsLock-Option", regs.end[i] - regs.start[i]) == 0) 346 table |= B_OPTION_CAPS_TABLE; 347 else if (strncmp(buffer + regs.start[i], "CapsLock-Option-Shift", regs.end[i] - regs.start[i]) == 0) 348 table |= B_OPTION_CAPS_SHIFT_TABLE; 349 } 350 } 351 352 353 status_t 354 Keymap::LoadSourceFromRef(entry_ref &ref) 355 { 356 status_t err; 357 358 BFile file(&ref, B_READ_ONLY); 359 if ((err = file.InitCheck()) != B_OK) { 360 printf("error %s\n", strerror(err)); 361 return err; 362 } 363 364 int fd = file.Dup(); 365 FILE * f = fdopen(fd, "r"); 366 367 return LoadSource(f); 368 } 369 370 371 // i couldn't put patterns and pattern bufs on the stack without segfaulting 372 // regexp patterns 373 const char versionPattern[] = "Version[[:space:]]+=[[:space:]]+\\([[:digit:]]+\\)"; 374 const char capslockPattern[] = "CapsLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 375 const char scrolllockPattern[] = "ScrollLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 376 const char numlockPattern[] = "NumLock[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 377 const char lshiftPattern[] = "LShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 378 const char rshiftPattern[] = "RShift[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 379 const char lcommandPattern[] = "LCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 380 const char rcommandPattern[] = "RCommand[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 381 const char lcontrolPattern[] = "LControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 382 const char rcontrolPattern[] = "RControl[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 383 const char loptionPattern[] = "LOption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 384 const char roptionPattern[] = "ROption[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 385 const char menuPattern[] = "Menu[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\)"; 386 const char locksettingsPattern[] = "LockSettings[[:space:]]+=[[:space:]]+\\([[:alnum:]]*\\)" 387 "[[:space:]]*\\([[:alnum:]]*\\)" 388 "[[:space:]]*\\([[:alnum:]]*\\)[[:space:]]*"; 389 const char keyPattern[] = "Key[[:space:]]+\\([[:alnum:]]+\\)[[:space:]]+=" 390 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 391 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 392 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 393 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 394 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 395 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 396 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 397 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 398 "[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)" 399 "[[:space:]]+"; 400 401 402 const char acutePattern[] = "Acute[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; 403 const char gravePattern[] = "Grave[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; 404 const char circumflexPattern[] = "Circumflex[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; 405 const char diaeresisPattern[] = "Diaeresis[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; 406 const char tildePattern[] = "Tilde[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+=[[:space:]]+\\([[:alnum:]]+\\|'.*'\\)[[:space:]]+"; 407 const char acutetabPattern[] = "AcuteTab[[:space:]]+=" 408 "[[:space:]]+\\([[:alnum:]-]*\\)" 409 "[[:space:]]*\\([[:alnum:]-]*\\)" 410 "[[:space:]]*\\([[:alnum:]-]*\\)" 411 "[[:space:]]*\\([[:alnum:]-]*\\)" 412 "[[:space:]]*\\([[:alnum:]-]*\\)" 413 "[[:space:]]*\\([[:alnum:]-]*\\)" 414 "[[:space:]]*\\([[:alnum:]-]*\\)" 415 "[[:space:]]*\\([[:alnum:]-]*\\)" 416 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; 417 const char gravetabPattern[] = "GraveTab[[:space:]]+=" 418 "[[:space:]]+\\([[:alnum:]-]*\\)" 419 "[[:space:]]*\\([[:alnum:]-]*\\)" 420 "[[:space:]]*\\([[:alnum:]-]*\\)" 421 "[[:space:]]*\\([[:alnum:]-]*\\)" 422 "[[:space:]]*\\([[:alnum:]-]*\\)" 423 "[[:space:]]*\\([[:alnum:]-]*\\)" 424 "[[:space:]]*\\([[:alnum:]-]*\\)" 425 "[[:space:]]*\\([[:alnum:]-]*\\)" 426 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; 427 const char circumflextabPattern[] = "CircumflexTab[[:space:]]+=" 428 "[[:space:]]+\\([[:alnum:]-]*\\)" 429 "[[:space:]]*\\([[:alnum:]-]*\\)" 430 "[[:space:]]*\\([[:alnum:]-]*\\)" 431 "[[:space:]]*\\([[:alnum:]-]*\\)" 432 "[[:space:]]*\\([[:alnum:]-]*\\)" 433 "[[:space:]]*\\([[:alnum:]-]*\\)" 434 "[[:space:]]*\\([[:alnum:]-]*\\)" 435 "[[:space:]]*\\([[:alnum:]-]*\\)" 436 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; 437 const char diaeresistabPattern[] = "DiaeresisTab[[:space:]]+=" 438 "[[:space:]]+\\([[:alnum:]-]*\\)" 439 "[[:space:]]*\\([[:alnum:]-]*\\)" 440 "[[:space:]]*\\([[:alnum:]-]*\\)" 441 "[[:space:]]*\\([[:alnum:]-]*\\)" 442 "[[:space:]]*\\([[:alnum:]-]*\\)" 443 "[[:space:]]*\\([[:alnum:]-]*\\)" 444 "[[:space:]]*\\([[:alnum:]-]*\\)" 445 "[[:space:]]*\\([[:alnum:]-]*\\)" 446 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; 447 const char tildetabPattern[] = "TildeTab[[:space:]]+=" 448 "[[:space:]]+\\([[:alnum:]-]*\\)" 449 "[[:space:]]*\\([[:alnum:]-]*\\)" 450 "[[:space:]]*\\([[:alnum:]-]*\\)" 451 "[[:space:]]*\\([[:alnum:]-]*\\)" 452 "[[:space:]]*\\([[:alnum:]-]*\\)" 453 "[[:space:]]*\\([[:alnum:]-]*\\)" 454 "[[:space:]]*\\([[:alnum:]-]*\\)" 455 "[[:space:]]*\\([[:alnum:]-]*\\)" 456 "[[:space:]]*\\([[:alnum:]-]*\\)[[:space:]]*" ; 457 458 459 // re_pattern_buffer buffers 460 struct re_pattern_buffer versionBuf; 461 struct re_pattern_buffer capslockBuf; 462 struct re_pattern_buffer scrolllockBuf; 463 struct re_pattern_buffer numlockBuf; 464 struct re_pattern_buffer lshiftBuf; 465 struct re_pattern_buffer rshiftBuf; 466 struct re_pattern_buffer lcommandBuf; 467 struct re_pattern_buffer rcommandBuf; 468 struct re_pattern_buffer lcontrolBuf; 469 struct re_pattern_buffer rcontrolBuf; 470 struct re_pattern_buffer loptionBuf; 471 struct re_pattern_buffer roptionBuf; 472 struct re_pattern_buffer menuBuf; 473 struct re_pattern_buffer locksettingsBuf; 474 struct re_pattern_buffer keyBuf; 475 struct re_pattern_buffer acuteBuf; 476 struct re_pattern_buffer graveBuf; 477 struct re_pattern_buffer circumflexBuf; 478 struct re_pattern_buffer diaeresisBuf; 479 struct re_pattern_buffer tildeBuf; 480 struct re_pattern_buffer acutetabBuf; 481 struct re_pattern_buffer gravetabBuf; 482 struct re_pattern_buffer circumflextabBuf; 483 struct re_pattern_buffer diaeresistabBuf; 484 struct re_pattern_buffer tildetabBuf; 485 486 status_t 487 Keymap::LoadSource(FILE * f) 488 { 489 reg_syntax_t syntax = RE_CHAR_CLASSES; 490 re_set_syntax(syntax); 491 492 const char* error; 493 error = re_compile_pattern(versionPattern, strlen(versionPattern), &versionBuf); 494 if (error) 495 fprintf(stderr, error); 496 error = re_compile_pattern(capslockPattern, strlen(capslockPattern), &capslockBuf); 497 if (error) 498 fprintf(stderr, error); 499 error = re_compile_pattern(scrolllockPattern, strlen(scrolllockPattern), &scrolllockBuf); 500 if (error) 501 fprintf(stderr, error); 502 error = re_compile_pattern(numlockPattern, strlen(numlockPattern), &numlockBuf); 503 if (error) 504 fprintf(stderr, error); 505 error = re_compile_pattern(lshiftPattern, strlen(lshiftPattern), &lshiftBuf); 506 if (error) 507 fprintf(stderr, error); 508 error = re_compile_pattern(rshiftPattern, strlen(rshiftPattern), &rshiftBuf); 509 if (error) 510 fprintf(stderr, error); 511 error = re_compile_pattern(lcommandPattern, strlen(lcommandPattern), &lcommandBuf); 512 if (error) 513 fprintf(stderr, error); 514 error = re_compile_pattern(rcommandPattern, strlen(rcommandPattern), &rcommandBuf); 515 if (error) 516 fprintf(stderr, error); 517 error = re_compile_pattern(lcontrolPattern, strlen(lcontrolPattern), &lcontrolBuf); 518 if (error) 519 fprintf(stderr, error); 520 error = re_compile_pattern(rcontrolPattern, strlen(rcontrolPattern), &rcontrolBuf); 521 if (error) 522 fprintf(stderr, error); 523 error = re_compile_pattern(loptionPattern, strlen(loptionPattern), &loptionBuf); 524 if (error) 525 fprintf(stderr, error); 526 error = re_compile_pattern(roptionPattern, strlen(roptionPattern), &roptionBuf); 527 if (error) 528 fprintf(stderr, error); 529 error = re_compile_pattern(menuPattern, strlen(menuPattern), &menuBuf); 530 if (error) 531 fprintf(stderr, error); 532 error = re_compile_pattern(locksettingsPattern, strlen(locksettingsPattern), &locksettingsBuf); 533 if (error) 534 fprintf(stderr, error); 535 error = re_compile_pattern(keyPattern, strlen(keyPattern), &keyBuf); 536 if (error) 537 fprintf(stderr, error); 538 error = re_compile_pattern(acutePattern, strlen(acutePattern), ´Buf); 539 if (error) 540 fprintf(stderr, error); 541 error = re_compile_pattern(gravePattern, strlen(gravePattern), &graveBuf); 542 if (error) 543 fprintf(stderr, error); 544 error = re_compile_pattern(circumflexPattern, strlen(circumflexPattern), &circumflexBuf); 545 if (error) 546 fprintf(stderr, error); 547 error = re_compile_pattern(diaeresisPattern, strlen(diaeresisPattern), &diaeresisBuf); 548 if (error) 549 fprintf(stderr, error); 550 error = re_compile_pattern(tildePattern, strlen(tildePattern), &tildeBuf); 551 if (error) 552 fprintf(stderr, error); 553 error = re_compile_pattern(acutetabPattern, strlen(acutetabPattern), ´tabBuf); 554 if (error) 555 fprintf(stderr, error); 556 error = re_compile_pattern(gravetabPattern, strlen(gravetabPattern), &gravetabBuf); 557 if (error) 558 fprintf(stderr, error); 559 error = re_compile_pattern(circumflextabPattern, strlen(circumflextabPattern), &circumflextabBuf); 560 if (error) 561 fprintf(stderr, error); 562 error = re_compile_pattern(diaeresistabPattern, strlen(diaeresistabPattern), &diaeresistabBuf); 563 if (error) 564 fprintf(stderr, error); 565 error = re_compile_pattern(tildetabPattern, strlen(tildetabPattern), &tildetabBuf); 566 if (error) 567 fprintf(stderr, error); 568 569 570 char buffer[1024]; 571 572 delete [] fChars; 573 fChars = new char[CHARS_TABLE_MAXSIZE]; 574 fCharsSize = CHARS_TABLE_MAXSIZE; 575 int offset = 0; 576 int acuteOffset = 0; 577 int graveOffset = 0; 578 int circumflexOffset = 0; 579 int diaeresisOffset = 0; 580 int tildeOffset = 0; 581 582 int32 *maps[] = { 583 fKeys.normal_map, 584 fKeys.shift_map, 585 fKeys.control_map, 586 fKeys.option_map, 587 fKeys.option_shift_map, 588 fKeys.caps_map, 589 fKeys.caps_shift_map, 590 fKeys.option_caps_map, 591 fKeys.option_caps_shift_map 592 }; 593 594 while (fgets(buffer, 1024-1, f)!=NULL) { 595 if (buffer[0]== '#' || buffer[0]== '\n') 596 continue; 597 struct re_registers regs; 598 if (re_search(&versionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 599 sscanf(buffer + regs.start[1], "%ld", &fKeys.version); 600 } else if (re_search(&capslockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 601 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.caps_key); 602 } else if (re_search(&scrolllockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 603 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.scroll_key); 604 } else if (re_search(&numlockBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 605 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.num_key); 606 } else if (re_search(&lshiftBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 607 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_shift_key); 608 } else if (re_search(&rshiftBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 609 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_shift_key); 610 } else if (re_search(&lcommandBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 611 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_command_key); 612 } else if (re_search(&rcommandBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 613 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_command_key); 614 } else if (re_search(&lcontrolBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 615 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_control_key); 616 } else if (re_search(&rcontrolBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 617 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_control_key); 618 } else if (re_search(&loptionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 619 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.left_option_key); 620 } else if (re_search(&roptionBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 621 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.right_option_key); 622 } else if (re_search(&menuBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 623 sscanf(buffer + regs.start[1], "0x%lx", &fKeys.menu_key); 624 } else if (re_search(&locksettingsBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 625 fKeys.lock_settings = 0; 626 for (int32 i=1; i<=3; i++) { 627 if (regs.end[i] - regs.start[i] <= 0) 628 break; 629 if (strncmp(buffer + regs.start[i], "CapsLock", regs.end[i] - regs.start[i]) == 0) 630 fKeys.lock_settings |= B_CAPS_LOCK; 631 else if (strncmp(buffer + regs.start[i], "NumLock", regs.end[i] - regs.start[i]) == 0) 632 fKeys.lock_settings |= B_NUM_LOCK; 633 else if (strncmp(buffer + regs.start[i], "ScrollLock", regs.end[i] - regs.start[i]) == 0) 634 fKeys.lock_settings |= B_SCROLL_LOCK; 635 } 636 } else if (re_search(&keyBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 637 uint32 keyCode; 638 if (sscanf(buffer + regs.start[1], "0x%lx", &keyCode) > 0) { 639 640 for (int i=2; i<=10; i++) { 641 maps[i-2][keyCode] = offset; 642 ComputeChars(buffer, regs, i, offset); 643 } 644 } 645 } else if (re_search(´Buf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 646 for (int i=1; i<=2; i++) { 647 fKeys.acute_dead_key[acuteOffset++] = offset; 648 ComputeChars(buffer, regs, i, offset); 649 } 650 } else if (re_search(&graveBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 651 for (int i=1; i<=2; i++) { 652 fKeys.grave_dead_key[graveOffset++] = offset; 653 ComputeChars(buffer, regs, i, offset); 654 } 655 } else if (re_search(&circumflexBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 656 for (int i=1; i<=2; i++) { 657 fKeys.circumflex_dead_key[circumflexOffset++] = offset; 658 ComputeChars(buffer, regs, i, offset); 659 } 660 } else if (re_search(&diaeresisBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 661 for (int i=1; i<=2; i++) { 662 fKeys.dieresis_dead_key[diaeresisOffset++] = offset; 663 ComputeChars(buffer, regs, i, offset); 664 } 665 } else if (re_search(&tildeBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 666 for (int i=1; i<=2; i++) { 667 fKeys.tilde_dead_key[tildeOffset++] = offset; 668 ComputeChars(buffer, regs, i, offset); 669 } 670 } else if (re_search(´tabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 671 ComputeTables(buffer, regs, fKeys.acute_tables); 672 } else if (re_search(&gravetabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 673 ComputeTables(buffer, regs, fKeys.grave_tables); 674 } else if (re_search(&circumflextabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 675 ComputeTables(buffer, regs, fKeys.circumflex_tables); 676 } else if (re_search(&diaeresistabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 677 ComputeTables(buffer, regs, fKeys.dieresis_tables); 678 } else if (re_search(&tildetabBuf, buffer, strlen(buffer), 0, strlen(buffer), ®s) >= 0) { 679 ComputeTables(buffer, regs, fKeys.tilde_tables); 680 } 681 } 682 683 fCharsSize = offset; 684 685 if (fKeys.version != 3) 686 return B_ERROR; 687 688 return B_OK; 689 } 690 691 692 // we save a map to a file 693 status_t 694 Keymap::Save(entry_ref &ref) 695 { 696 status_t err; 697 698 BFile file(&ref, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE ); 699 if ((err = file.InitCheck()) != B_OK) { 700 printf("error %s\n", strerror(err)); 701 return err; 702 } 703 704 for (uint32 i=0; i<sizeof(fKeys)/4; i++) 705 ((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]); 706 707 if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys)) { 708 return err; 709 } 710 711 for (uint32 i=0; i<sizeof(fKeys)/4; i++) 712 ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); 713 714 fCharsSize = B_HOST_TO_BENDIAN_INT32(fCharsSize); 715 716 if ((err = file.Write(&fCharsSize, sizeof(uint32))) < (ssize_t)sizeof(uint32)) { 717 return B_BAD_VALUE; 718 } 719 720 fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); 721 722 if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize) 723 return err; 724 725 return B_OK; 726 } 727 728 729 const char header_header[] = 730 "/*\tHaiku \t*/\n" 731 "/*\n" 732 " This file is generated automatically. Don't edit ! \n" 733 "*/\n\n"; 734 735 void 736 Keymap::SaveAsHeader(entry_ref &ref) 737 { 738 status_t err; 739 740 BFile file(&ref, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE ); 741 if ((err = file.InitCheck()) != B_OK) { 742 printf("error %s\n", strerror(err)); 743 return; 744 } 745 746 int fd = file.Dup(); 747 FILE * f = fdopen(fd, "w"); 748 749 fprintf(f, "%s", header_header); 750 fprintf(f, "#include <InterfaceDefs.h>\n\n"); 751 fprintf(f, "const key_map sSystemKeymap = {\n"); 752 fprintf(f, "\tversion:%ld,\n", fKeys.version); 753 fprintf(f, "\tcaps_key:0x%lx,\n", fKeys.caps_key); 754 fprintf(f, "\tscroll_key:0x%lx,\n", fKeys.scroll_key); 755 fprintf(f, "\tnum_key:0x%lx,\n", fKeys.num_key); 756 fprintf(f, "\tleft_shift_key:0x%lx,\n", fKeys.left_shift_key); 757 fprintf(f, "\tright_shift_key:0x%lx,\n", fKeys.right_shift_key); 758 fprintf(f, "\tleft_command_key:0x%lx,\n", fKeys.left_command_key); 759 fprintf(f, "\tright_command_key:0x%lx,\n", fKeys.right_command_key); 760 fprintf(f, "\tleft_control_key:0x%lx,\n", fKeys.left_control_key); 761 fprintf(f, "\tright_control_key:0x%lx,\n", fKeys.right_control_key); 762 fprintf(f, "\tleft_option_key:0x%lx,\n", fKeys.left_option_key); 763 fprintf(f, "\tright_option_key:0x%lx,\n", fKeys.right_option_key); 764 fprintf(f, "\tmenu_key:0x%lx,\n", fKeys.menu_key); 765 fprintf(f, "\tlock_settings:0x%lx,\n", fKeys.lock_settings); 766 767 fprintf(f, "\tcontrol_map:{\n"); 768 for (uint32 i=0; i<128; i++) 769 fprintf(f, "\t\t%ld,\n", fKeys.control_map[i]); 770 fprintf(f, "\t},\n"); 771 772 fprintf(f, "\toption_caps_shift_map:{\n"); 773 for (uint32 i=0; i<128; i++) 774 fprintf(f, "\t\t%ld,\n", fKeys.option_caps_shift_map[i]); 775 fprintf(f, "\t},\n"); 776 777 fprintf(f, "\toption_caps_map:{\n"); 778 for (uint32 i=0; i<128; i++) 779 fprintf(f, "\t\t%ld,\n", fKeys.option_caps_map[i]); 780 fprintf(f, "\t},\n"); 781 782 fprintf(f, "\toption_shift_map:{\n"); 783 for (uint32 i=0; i<128; i++) 784 fprintf(f, "\t\t%ld,\n", fKeys.option_shift_map[i]); 785 fprintf(f, "\t},\n"); 786 787 fprintf(f, "\toption_map:{\n"); 788 for (uint32 i=0; i<128; i++) 789 fprintf(f, "\t\t%ld,\n", fKeys.option_map[i]); 790 fprintf(f, "\t},\n"); 791 792 fprintf(f, "\tcaps_shift_map:{\n"); 793 for (uint32 i=0; i<128; i++) 794 fprintf(f, "\t\t%ld,\n", fKeys.caps_shift_map[i]); 795 fprintf(f, "\t},\n"); 796 797 fprintf(f, "\tcaps_map:{\n"); 798 for (uint32 i=0; i<128; i++) 799 fprintf(f, "\t\t%ld,\n", fKeys.caps_map[i]); 800 fprintf(f, "\t},\n"); 801 802 fprintf(f, "\tshift_map:{\n"); 803 for (uint32 i=0; i<128; i++) 804 fprintf(f, "\t\t%ld,\n", fKeys.shift_map[i]); 805 fprintf(f, "\t},\n"); 806 807 fprintf(f, "\tnormal_map:{\n"); 808 for (uint32 i=0; i<128; i++) 809 fprintf(f, "\t\t%ld,\n", fKeys.normal_map[i]); 810 fprintf(f, "\t},\n"); 811 812 fprintf(f, "\tacute_dead_key:{\n"); 813 for (uint32 i=0; i<32; i++) 814 fprintf(f, "\t\t%ld,\n", fKeys.acute_dead_key[i]); 815 fprintf(f, "\t},\n"); 816 817 fprintf(f, "\tgrave_dead_key:{\n"); 818 for (uint32 i=0; i<32; i++) 819 fprintf(f, "\t\t%ld,\n", fKeys.grave_dead_key[i]); 820 fprintf(f, "\t},\n"); 821 822 fprintf(f, "\tcircumflex_dead_key:{\n"); 823 for (uint32 i=0; i<32; i++) 824 fprintf(f, "\t\t%ld,\n", fKeys.circumflex_dead_key[i]); 825 fprintf(f, "\t},\n"); 826 827 fprintf(f, "\tdieresis_dead_key:{\n"); 828 for (uint32 i=0; i<32; i++) 829 fprintf(f, "\t\t%ld,\n", fKeys.dieresis_dead_key[i]); 830 fprintf(f, "\t},\n"); 831 832 fprintf(f, "\ttilde_dead_key:{\n"); 833 for (uint32 i=0; i<32; i++) 834 fprintf(f, "\t\t%ld,\n", fKeys.tilde_dead_key[i]); 835 fprintf(f, "\t},\n"); 836 837 fprintf(f, "\tacute_tables:0x%lx,\n", fKeys.acute_tables); 838 fprintf(f, "\tgrave_tables:0x%lx,\n", fKeys.grave_tables); 839 fprintf(f, "\tcircumflex_tables:0x%lx,\n", fKeys.circumflex_tables); 840 fprintf(f, "\tdieresis_tables:0x%lx,\n", fKeys.dieresis_tables); 841 fprintf(f, "\ttilde_tables:0x%lx,\n", fKeys.tilde_tables); 842 843 fprintf(f, "};\n\n"); 844 845 fprintf(f, "const char sSystemKeyChars[] = {\n"); 846 for (uint32 i=0; i<fCharsSize; i++) 847 fprintf(f, "\t%hhd,\n", fChars[i]); 848 fprintf(f, "};\n\n"); 849 850 fprintf(f, "const uint32 sSystemKeyCharsSize = %ld;\n", fCharsSize); 851 } 852 853 854 /* we need to know if a key is a modifier key to choose 855 a valid key when several are pressed together 856 */ 857 bool 858 Keymap::IsModifierKey(uint32 keyCode) 859 { 860 if ((keyCode == fKeys.caps_key) 861 || (keyCode == fKeys.num_key) 862 || (keyCode == fKeys.left_shift_key) 863 || (keyCode == fKeys.right_shift_key) 864 || (keyCode == fKeys.left_command_key) 865 || (keyCode == fKeys.right_command_key) 866 || (keyCode == fKeys.left_control_key) 867 || (keyCode == fKeys.right_control_key) 868 || (keyCode == fKeys.left_option_key) 869 || (keyCode == fKeys.right_option_key) 870 || (keyCode == fKeys.menu_key)) 871 return true; 872 return false; 873 } 874 875 876 // tell if a key is a dead key, needed for draw a dead key 877 uint8 878 Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) 879 { 880 int32 offset; 881 uint32 tableMask = 0; 882 883 switch (modifiers & 0xcf) { 884 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; tableMask = B_SHIFT_TABLE; break; 885 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; tableMask = B_CAPS_TABLE; break; 886 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; tableMask = B_CAPS_SHIFT_TABLE; break; 887 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; tableMask = B_OPTION_TABLE; break; 888 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; tableMask = B_OPTION_SHIFT_TABLE; break; 889 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; tableMask = B_OPTION_CAPS_TABLE; break; 890 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; tableMask = B_OPTION_CAPS_SHIFT_TABLE; break; 891 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; tableMask = B_CONTROL_TABLE; break; 892 default: offset = fKeys.normal_map[keyCode]; tableMask = B_NORMAL_TABLE; break; 893 } 894 895 if (offset<=0) 896 return 0; 897 uint32 numBytes = fChars[offset]; 898 899 if (!numBytes) 900 return 0; 901 902 char chars[4]; 903 strncpy(chars, &(fChars[offset+1]), numBytes ); 904 chars[numBytes] = 0; 905 906 int32 deadOffsets[] = { 907 fKeys.acute_dead_key[1], 908 fKeys.grave_dead_key[1], 909 fKeys.circumflex_dead_key[1], 910 fKeys.dieresis_dead_key[1], 911 fKeys.tilde_dead_key[1] 912 }; 913 914 uint32 deadTables[] = { 915 fKeys.acute_tables, 916 fKeys.grave_tables, 917 fKeys.circumflex_tables, 918 fKeys.dieresis_tables, 919 fKeys.tilde_tables 920 }; 921 922 for (int32 i=0; i<5; i++) { 923 if ((deadTables[i] & tableMask) == 0) 924 continue; 925 926 if (offset == deadOffsets[i]) 927 return i+1; 928 929 uint32 deadNumBytes = fChars[deadOffsets[i]]; 930 931 if (!deadNumBytes) 932 continue; 933 934 if (strncmp(chars, &(fChars[deadOffsets[i]+1]), deadNumBytes ) == 0) { 935 return i+1; 936 } 937 } 938 return 0; 939 } 940 941 942 // tell if a key is a dead second key, needed for draw a dead second key 943 bool 944 Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) 945 { 946 if (!activeDeadKey) 947 return false; 948 949 int32 offset; 950 951 switch (modifiers & 0xcf) { 952 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; 953 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; 954 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; 955 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; 956 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; 957 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; 958 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; 959 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; 960 default: offset = fKeys.normal_map[keyCode]; break; 961 } 962 963 uint32 numBytes = fChars[offset]; 964 965 if (!numBytes) 966 return false; 967 968 int32* deadOffsets[] = { 969 fKeys.acute_dead_key, 970 fKeys.grave_dead_key, 971 fKeys.circumflex_dead_key, 972 fKeys.dieresis_dead_key, 973 fKeys.tilde_dead_key 974 }; 975 976 int32 *deadOffset = deadOffsets[activeDeadKey-1]; 977 978 for (int32 i=0; i<32; i++) { 979 if (offset == deadOffset[i]) 980 return true; 981 982 uint32 deadNumBytes = fChars[deadOffset[i]]; 983 984 if (!deadNumBytes) 985 continue; 986 987 if (strncmp(&(fChars[offset+1]), &(fChars[deadOffset[i]+1]), deadNumBytes ) == 0) 988 return true; 989 i++; 990 } 991 return false; 992 } 993 994 995 // get the char for a key given modifiers and active dead key 996 void 997 Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, char** chars, int32* numBytes) 998 { 999 int32 offset; 1000 1001 *numBytes = 0; 1002 *chars = NULL; 1003 1004 // here we take NUMLOCK into account 1005 if (modifiers & B_NUM_LOCK) 1006 switch (keyCode) { 1007 case 0x37: 1008 case 0x38: 1009 case 0x39: 1010 case 0x48: 1011 case 0x49: 1012 case 0x4a: 1013 case 0x58: 1014 case 0x59: 1015 case 0x5a: 1016 case 0x64: 1017 case 0x65: 1018 modifiers ^= B_SHIFT_KEY; 1019 } 1020 1021 // here we choose the right map given the modifiers 1022 switch (modifiers & 0xcf) { 1023 case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; 1024 case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; 1025 case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; 1026 case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; 1027 case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; 1028 case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; 1029 case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; 1030 case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; 1031 default: offset = fKeys.normal_map[keyCode]; break; 1032 } 1033 1034 // here we get the char size 1035 *numBytes = fChars[offset]; 1036 1037 if (!*numBytes) 1038 return; 1039 1040 // here we take an potential active dead key 1041 int32 *dead_key; 1042 switch(activeDeadKey) { 1043 case 1: dead_key = fKeys.acute_dead_key; break; 1044 case 2: dead_key = fKeys.grave_dead_key; break; 1045 case 3: dead_key = fKeys.circumflex_dead_key; break; 1046 case 4: dead_key = fKeys.dieresis_dead_key; break; 1047 case 5: dead_key = fKeys.tilde_dead_key; break; 1048 default: 1049 { 1050 // if not dead, we copy and return the char 1051 char *str = *chars = new char[*numBytes + 1]; 1052 strncpy(str, &(fChars[offset+1]), *numBytes ); 1053 str[*numBytes] = 0; 1054 return; 1055 } 1056 } 1057 1058 // if dead key, we search for our current offset char in the dead key offset table 1059 // string comparison is needed 1060 for (int32 i=0; i<32; i++) { 1061 if (strncmp(&(fChars[offset+1]), &(fChars[dead_key[i]+1]), *numBytes ) == 0) { 1062 *numBytes = fChars[dead_key[i+1]]; 1063 1064 switch( *numBytes ) { 1065 case 0: 1066 // Not mapped 1067 *chars = NULL; 1068 break; 1069 default: 1070 // 1-, 2-, 3-, or 4-byte UTF-8 character 1071 { 1072 char *str = *chars = new char[*numBytes + 1]; 1073 strncpy(str, &fChars[dead_key[i+1]+1], *numBytes ); 1074 str[*numBytes] = 0; 1075 } 1076 break; 1077 } 1078 return; 1079 } 1080 i++; 1081 } 1082 1083 // if not found we return the current char mapped 1084 *chars = new char[*numBytes + 1]; 1085 strncpy(*chars, &(fChars[offset+1]), *numBytes ); 1086 (*chars)[*numBytes] = 0; 1087 1088 } 1089 1090 status_t _restore_key_map_(); 1091 1092 1093 void 1094 Keymap::RestoreSystemDefault() 1095 { 1096 #ifdef __BEOS__ 1097 // work-around to get rid of this stupid find_directory_r() on Zeta 1098 # ifdef find_directory 1099 # undef find_directory 1100 # endif 1101 BPath path; 1102 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK) 1103 return; 1104 1105 path.Append("Key_map"); 1106 1107 BEntry ref(path.Path()); 1108 ref.Remove(); 1109 1110 _restore_key_map_(); 1111 #else // ! __BEOS__ 1112 fprintf(stderr, "Unsupported operation on this platform!\n"); 1113 exit(1); 1114 #endif // ! __BEOS__ 1115 } 1116 1117 1118 void 1119 Keymap::SaveAsCurrent() 1120 { 1121 #ifdef __BEOS__ 1122 1123 BPath path; 1124 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK) 1125 return; 1126 1127 path.Append("Key_map"); 1128 1129 entry_ref ref; 1130 get_ref_for_path(path.Path(), &ref); 1131 1132 status_t err; 1133 if ((err = Save(ref)) != B_OK) { 1134 printf("error when saving : %s", strerror(err)); 1135 return; 1136 } 1137 Use(); 1138 1139 #else // ! __BEOS__ 1140 fprintf(stderr, "Unsupported operation on this platform!\n"); 1141 exit(1); 1142 #endif // ! __BEOS__ 1143 } 1144 1145 1146 // we make our input server use the map in /boot/home/config/settings/Keymap 1147 status_t 1148 Keymap::Use() 1149 { 1150 #ifdef __BEOS__ 1151 1152 return _restore_key_map_(); 1153 1154 #else // ! __BEOS__ 1155 fprintf(stderr, "Unsupported operation on this platform!\n"); 1156 exit(1); 1157 #endif // ! __BEOS__ 1158 } 1159