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