1 /* 2 * PROJECT: ReactOS Build Tools [Keyboard Layout Compiler] 3 * LICENSE: BSD - See COPYING.BSD in the top level directory 4 * FILE: tools/kbdtool/output.c 5 * PURPOSE: Output Logic (Source Builder) 6 * PROGRAMMERS: ReactOS Foundation 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include "kbdtool.h" 12 13 /* GLOBALS ********************************************************************/ 14 15 ULONG gStringIdForDescriptions = 1000; 16 ULONG gStringIdForLanguageNames = 1100; 17 ULONG gStringIdForLocaleName = 1200; 18 time_t Clock; 19 struct tm *Now; 20 CHAR gCharName[32]; 21 22 /* FUNCTIONS ******************************************************************/ 23 24 PCHAR 25 WChName(IN ULONG Char, 26 IN BOOLEAN AddZero) 27 { 28 PCHAR p; 29 30 /* Check for invalid character */ 31 if (Char == -1) 32 { 33 /* No name */ 34 strcpy(gCharName, "WCH_NONE"); 35 } 36 else if ((Char > 31) && (Char < 128)) 37 { 38 /* Use our global buffer */ 39 p = gCharName; 40 41 /* Add the first quote unless this was a zero-string */ 42 if (!AddZero) *p++ = '\''; 43 44 /* Now replace any other quote or comment character with a slash */ 45 if ((Char == '\"') || (Char == '\'') || (Char == '\\')) *p++ = '\\'; 46 47 /* Now plug in the character */ 48 *p++ = Char; 49 50 /* And add the terminating quote, unless this was a zero-string */ 51 if (!AddZero) *p++ = '\''; 52 53 /* Terminate the buffer */ 54 *p = '\0'; 55 } 56 else 57 { 58 /* Handle special cases */ 59 if (Char == '\b') 60 { 61 /* Bell */ 62 strcpy(gCharName, "'\\b'"); 63 } 64 else if (Char == '\n') 65 { 66 /* New line */ 67 strcpy(gCharName, "'\\n'"); 68 } 69 else if (Char == '\r') 70 { 71 /* Return */ 72 strcpy(gCharName, "'\\r'"); 73 } 74 else if (!AddZero) 75 { 76 /* Char value, in hex */ 77 sprintf(gCharName, "0x%04x", Char); 78 } 79 else 80 { 81 /* Char value, C-style */ 82 sprintf(gCharName, "\\x%04x", Char); 83 } 84 } 85 86 /* Return the name */ 87 return gCharName; 88 } 89 90 VOID 91 PrintNameTable(FILE* FileHandle, 92 PKEYNAME KeyName, 93 BOOL DeadKey) 94 { 95 CHAR CharBuffer[255]; 96 PKEYNAME NextName; 97 PCHAR Name, Buffer; 98 ULONG i; 99 100 /* Loop all key names */ 101 while (KeyName) 102 { 103 /* Go to the next key name */ 104 NextName = KeyName->Next; 105 106 /* Remember the name and our buffer address */ 107 Name = KeyName->Name; 108 Buffer = CharBuffer; 109 110 /* Check if it's an IDS name */ 111 if (strncmp(Name, "IDS_", 4)) 112 { 113 /* No, so start parsing it. First, handle initial quote */ 114 if (*Name != '\"') *Buffer++ = '\"'; 115 116 /* Next, parse the name */ 117 while (*Name) 118 { 119 /* Check if this is a C-style hex string */ 120 if ((*Name != '\\') || ((*(Name + 1) != 'x') && (*(Name + 1) != 'X'))) 121 { 122 /* It's not, so just copy straight into our buffer */ 123 *Buffer++ = *Name++; 124 } 125 else 126 { 127 /* Continue scanning as long as this is a C-style hex string */ 128 while ((*Name == '\\') && ((*(Name + 1) == 'x') || (*(Name + 1) == 'X'))) 129 { 130 /* Copy 6 characters */ 131 for (i = 0; (*Name) && (i < 6); i++) *Buffer++ = *Name++; 132 } 133 134 /* Check if we still have something at the end */ 135 if (*Name) 136 { 137 /* Terminate our buffer */ 138 *Buffer++ = '\"'; 139 *Buffer++ = ' '; 140 *Buffer++ = 'L'; 141 *Buffer++ = '\"'; 142 } 143 } 144 } 145 146 /* Check for terminating quote */ 147 if (*(Buffer - 1) != '\"') *Buffer++ = '\"'; 148 149 /* Terminate the buffer */ 150 *Buffer++ = '\0'; 151 } 152 else 153 { 154 /* Not yet supported */ 155 printf("IDS Entries not yet handled!\n"); 156 exit(1); 157 } 158 159 /* Is this a dead key? */ 160 if (DeadKey) 161 { 162 /* Not yet handled */ 163 printf("Dead keys not yet handled\n"); 164 exit(1); 165 } 166 else 167 { 168 /* Print the entry */ 169 fprintf(FileHandle, " 0x%02x, L%s,\n", KeyName->Code, CharBuffer); 170 } 171 172 /* Cleanup allocation */ 173 free(KeyName->Name); 174 free(KeyName); 175 176 /* Move on */ 177 KeyName = NextName; 178 } 179 180 /* Is this a dead key? */ 181 if (DeadKey) 182 { 183 /* Not yet handled */ 184 printf("Dead keys not yet handled\n"); 185 exit(1); 186 } 187 else 188 { 189 /* Terminate the table */ 190 fprintf(FileHandle, " 0 , NULL\n"); 191 } 192 } 193 194 BOOLEAN 195 kbd_h(IN PLAYOUT Layout) 196 { 197 CHAR OutputFile[13]; 198 FILE *FileHandle; 199 ULONG i; 200 CHAR UndefChar; 201 USHORT SubCode; 202 203 /* Build the keyboard name */ 204 strcpy(OutputFile, gKBDName); 205 strcat(OutputFile, ".H"); 206 207 /* Open it */ 208 FileHandle = fopen(OutputFile, "wt"); 209 if (!FileHandle) 210 { 211 /* Fail */ 212 printf(" %12s : can't open for write.\n", OutputFile); 213 return FALSE; 214 } 215 216 /* Print the module header */ 217 fprintf(FileHandle, 218 "/****************************** Module Header ******************************\\\n" 219 "* Module Name: %s\n*\n* keyboard layout header\n" 220 "*\n" 221 "* Copyright (c) 2009, ReactOS Foundation\n" 222 "*\n" 223 "* Various defines for use by keyboard input code.\n*\n* History:\n" 224 "*\n" 225 "* created by KBDTOOL v%d.%02d %s*\n" 226 "\\***************************************************************************/\n\n", 227 OutputFile, 228 gVersion, 229 gSubVersion, 230 asctime(Now)); 231 232 /* Print out the includes and defines */ 233 fprintf(FileHandle, 234 "/*\n" 235 " * kbd type should be controlled by cl command-line argument\n" 236 " *\\n" 237 "#define KBD_TYPE 4\n\n" 238 "/*\n" 239 "* Include the basis of all keyboard table values\n" 240 "*/\n" 241 "#include \"kbd.h\"\n"); 242 243 /* Now print out the virtual key conversion table */ 244 fprintf(FileHandle, 245 "/***************************************************************************\\\n" 246 "* The table below defines the virtual keys for various keyboard types where\n" 247 "* the keyboard differ from the US keyboard.\n" 248 "*\n" 249 "* _EQ() : all keyboard types have the same virtual key for this scancode\n" 250 "* _NE() : different virtual keys for this scancode, depending on kbd type\n" 251 "*\n" 252 "* +------+ +----------+----------+----------+----------+----------+----------+\n" 253 "* | Scan | | kbd | kbd | kbd | kbd | kbd | kbd |\n" 254 "* | code | | type 1 | type 2 | type 3 | type 4 | type 5 | type 6 |\n" 255 "\\****+-------+_+----------+----------+----------+----------+----------+----------+*/\n\n"); 256 257 /* Loop all keys */ 258 for (i = 0; i < 110; i++) 259 { 260 /* Check if we processed this key */ 261 if (Layout->Entry[i].Processed) 262 { 263 /* Check if it redefined a virtual key */ 264 if (Layout->Entry[i].VirtualKey != Layout->Entry[i].OriginalVirtualKey) 265 { 266 /* Do we have a subcode? */ 267 SubCode = Layout->Entry[i].ScanCode & 0xFF00; 268 if (SubCode) 269 { 270 /* Which kind is it? */ 271 if (SubCode == 0xE000) 272 { 273 /* Extended 0 */ 274 UndefChar = 'X'; 275 } 276 else 277 { 278 /* Illegal */ 279 if (SubCode != 0xE100) 280 { 281 /* Unrecognized */ 282 printf("Weird scancode value %04x: expected xx, E0xx, or E1xx\n", SubCode); 283 exit(1); 284 } 285 286 /* Extended 1 */ 287 UndefChar = 'Y'; 288 } 289 } 290 else 291 { 292 /* Normal key */ 293 UndefChar = 'T'; 294 } 295 296 /* Print out the virtual key redefinition */ 297 fprintf(FileHandle, 298 "#undef %c%02X\n#define %c%02X _EQ(%43s%23s\n", 299 UndefChar, 300 Layout->Entry[i].ScanCode, 301 UndefChar, 302 Layout->Entry[i].ScanCode, 303 getVKName(Layout->Entry[i].VirtualKey, 0), 304 ")"); 305 } 306 } 307 } 308 309 /* Cleanup and close */ 310 fprintf(FileHandle,"\n"); 311 fclose(FileHandle); 312 313 /* We made it */ 314 return TRUE; 315 } 316 317 BOOLEAN 318 kbd_rc(IN PKEYNAME DescriptionData, 319 IN PKEYNAME LanguageData) 320 { 321 CHAR OutputFile[13]; 322 CHAR InternalName[13]; 323 CHAR TimeBuffer[5]; 324 FILE *FileHandle; 325 ULONG Length; 326 PCHAR p; 327 PKEYNAME NextDescription, NextLanguage; 328 329 /* Build the keyboard name and internal name */ 330 strcpy(OutputFile, gKBDName); 331 strcat(OutputFile, ".RC"); 332 strcpy(InternalName, gKBDName); 333 for (p = InternalName; *p; p++) *p = tolower(*p); 334 335 /* Open it */ 336 FileHandle = fopen(OutputFile, "wb"); 337 if (!FileHandle) 338 { 339 /* Fail */ 340 printf(" %12s : can't open for write.\n", OutputFile); 341 return FALSE; 342 } 343 344 /* Check if we have copyright */ 345 Length = strlen(gCopyright); 346 if (!Length) 347 { 348 /* Set time string */ 349 strftime(TimeBuffer, 5, "%Y", Now); 350 351 /* Add copyright character */ 352 strcpy(gCopyright, "(C)"); 353 354 /* Add the year */ 355 strcat(gCopyright, TimeBuffer); 356 357 /* Add blank company */ 358 strcat(gCopyright, " "); 359 } 360 361 /* Write the resource file header */ 362 fprintf(FileHandle, 363 "#include \"winver.h\"\r\n" 364 "1 VERSIONINFO\r\n" 365 " FILEVERSION 1,0,%d,%d\r\n" 366 " PRODUCTVERSION 1,0,%d,%d\r\n" 367 " FILEFLAGSMASK 0x3fL\r\n" 368 " FILEFLAGS 0x0L\r\n" 369 "FILEOS 0x40004L\r\n" 370 " FILETYPE VFT_DLL\r\n" 371 " FILESUBTYPE VFT2_DRV_KEYBOARD\r\n" 372 "BEGIN\r\n" 373 " BLOCK \"StringFileInfo\"\r\n" 374 " BEGIN\r\n" 375 " BLOCK \"000004B0\"\r\n" 376 " BEGIN\r\n" 377 " VALUE \"CompanyName\", \"%s\\0\"\r\n" 378 " VALUE \"FileDescription\", \"%s Keyboard Layout\\0\"\r\n" 379 " VALUE \"FileVersion\", \"1, 0, %d, %d\\0\"\r\n", 380 gVersion, 381 gSubVersion, 382 gVersion, 383 gSubVersion, 384 gCompany, 385 gDescription, 386 gVersion, 387 gSubVersion); 388 389 /* Continue writing it */ 390 fprintf(FileHandle, 391 " VALUE \"InternalName\", \"%s (%d.%d)\\0\"\r\n" 392 " VALUE \"ProductName\",\"%s\\0\"\r\n" 393 " VALUE \"Release Information\",\"%s\\0\"\r\n" 394 " VALUE \"LegalCopyright\", \"%s\\0\"\r\n" 395 " VALUE \"OriginalFilename\",\"%s\\0\"\r\n" 396 " VALUE \"ProductVersion\", \"1, 0, %d, %d\\0\"\r\n" 397 " END\r\n" 398 " END\r\n" 399 " BLOCK \"VarFileInfo\"\r\n" 400 " BEGIN\r\n" 401 " VALUE \"Translation\", 0x0000, 0x04B0\r\n" 402 " END\r\n" 403 "END\r\n", 404 InternalName, 405 gVersion, 406 gSubVersion, 407 "Created by ReactOS KbdTool", 408 "Created by ReactOS KbdTool", 409 gCopyright, 410 InternalName, 411 gVersion, 412 gSubVersion); 413 414 /* Now check if we have a locale name */ 415 Length = strlen(gLocaleName); 416 if (Length) 417 { 418 /* Write the stringtable header */ 419 fprintf(FileHandle, 420 "\r\nSTRINGTABLE DISCARDABLE\r\nLANGUAGE %d, %d\r\n", 421 9, 422 1); 423 fprintf(FileHandle, "BEGIN\r\n"); 424 425 /* Language or locale? */ 426 if (strchr(gLocaleName, '\"')) 427 { 428 /* Write the language name */ 429 fprintf(FileHandle, " %d %s\r\n", gStringIdForLanguageNames, gLocaleName); 430 } 431 else 432 { 433 /* Write the locale name */ 434 fprintf(FileHandle, " %d \"%s\"\r\n", gStringIdForLocaleName, gLocaleName); 435 } 436 437 /* Terminate the entry */ 438 fprintf(FileHandle, "END\r\n\r\n"); 439 } 440 441 /* Check for description information */ 442 while (DescriptionData) 443 { 444 /* Remember the next pointer */ 445 NextDescription = DescriptionData->Next; 446 447 /* Write the header */ 448 fprintf(FileHandle, 449 "\r\nSTRINGTABLE DISCARDABLE\r\nLANGUAGE %d, %d\r\n", 450 DescriptionData->Code & 0x3FF, 451 DescriptionData->Code >> 10); 452 fprintf(FileHandle, "BEGIN\r\n"); 453 454 /* Quoted string or not? */ 455 if (strchr(DescriptionData->Name, '\"')) 456 { 457 /* Write the description name */ 458 fprintf(FileHandle, " %d %s\r\n", gStringIdForDescriptions, DescriptionData->Name); 459 } 460 else 461 { 462 /* Write the description name */ 463 fprintf(FileHandle, " %d \"%s\"\r\n", gStringIdForDescriptions, DescriptionData->Name); 464 } 465 466 /* Terminate the entry */ 467 fprintf(FileHandle, "END\r\n\r\n"); 468 469 /* Free the allocation */ 470 free(DescriptionData->Name); 471 free(DescriptionData); 472 473 /* Move to the next entry */ 474 DescriptionData = NextDescription; 475 } 476 477 /* Check for language information */ 478 while (LanguageData) 479 { 480 /* Remember the next pointer */ 481 NextLanguage = LanguageData->Next; 482 483 /* Write the header */ 484 fprintf(FileHandle, 485 "\r\nSTRINGTABLE DISCARDABLE\r\nLANGUAGE %d, %d\r\n", 486 LanguageData->Code & 0x3FF, 487 LanguageData->Code >> 10); 488 fprintf(FileHandle, "BEGIN\r\n"); 489 490 /* Quoted string or not? */ 491 if (strchr(LanguageData->Name, '\"')) 492 { 493 /* Write the language name */ 494 fprintf(FileHandle, " %d %s\r\n", gStringIdForLanguageNames, LanguageData->Name); 495 } 496 else 497 { 498 /* Write the language name */ 499 fprintf(FileHandle, " %d \"%s\"\r\n", gStringIdForLanguageNames, LanguageData->Name); 500 } 501 502 /* Terminate the entry */ 503 fprintf(FileHandle, "END\r\n\r\n"); 504 505 /* Free the allocation */ 506 free(LanguageData->Name); 507 free(LanguageData); 508 509 /* Move to the next entry */ 510 LanguageData = NextLanguage; 511 } 512 513 /* We're done! */ 514 fclose(FileHandle); 515 return TRUE; 516 } 517 518 BOOLEAN 519 kbd_def(VOID) 520 { 521 CHAR OutputFile[13]; 522 FILE *FileHandle; 523 524 /* Build the keyboard name and internal name */ 525 strcpy(OutputFile, gKBDName); 526 strcat(OutputFile, ".DEF"); 527 528 /* Open it */ 529 FileHandle = fopen(OutputFile, "wt"); 530 if (!FileHandle) 531 { 532 /* Fail */ 533 printf(" %12s : can't open for write.\n", OutputFile); 534 return FALSE; 535 } 536 537 /* Write the file exports */ 538 fprintf(FileHandle, 539 "LIBRARY %s\n\n" 540 "EXPORTS\n" 541 " KbdLayerDescriptor @1\n", 542 gKBDName); 543 544 /* Clean up */ 545 fclose(FileHandle); 546 return TRUE; 547 } 548 549 BOOLEAN 550 kbd_c(IN ULONG StateCount, 551 IN PULONG ShiftStates, 552 IN PVOID AttributeData, 553 IN PLAYOUT Layout, 554 IN PVOID DeadKeyData, 555 IN PVOID LigatureData, 556 IN PKEYNAME KeyNameData, 557 IN PKEYNAME KeyNameExtData, 558 IN PKEYNAME KeyNameDeadData) 559 { 560 CHAR OutputFile[13]; 561 CHAR KeyNameBuffer[50]; 562 CHAR LineBuffer[256]; 563 BOOLEAN NeedPlus; 564 FILE *FileHandle; 565 ULONG States[8]; 566 ULONG i, j, k; 567 ULONG HighestState; 568 PVKNAME Entry; 569 PCHAR p; 570 571 /* Build the keyboard name and internal name */ 572 strcpy(OutputFile, gKBDName); 573 strcat(OutputFile, ".C"); 574 575 /* Open it */ 576 FileHandle = fopen(OutputFile, "wt"); 577 if (!FileHandle) 578 { 579 /* Fail */ 580 printf(" %12s : can't open for write.\n", OutputFile); 581 return FALSE; 582 } 583 584 /* Print the header */ 585 fprintf(FileHandle, 586 "/***************************************************************************\\\n" 587 "* Module Name: %s\n*\n* keyboard layout\n" 588 "*\n" 589 "* Copyright (c) 2009, ReactOS Foundation\n" 590 "*\n" 591 "* History:\n" 592 "* KBDTOOL v%d.%02d - Created %s" 593 "\\***************************************************************************/\n\n", 594 OutputFile, 595 gVersion, 596 gSubVersion, 597 asctime(Now)); 598 599 /* What kind of driver is this? */ 600 if (FallbackDriver) 601 { 602 /* Fallback only */ 603 fprintf(FileHandle, "#include \"precomp.h\"\n"); 604 } 605 else 606 { 607 /* Add the includes */ 608 fprintf(FileHandle, 609 "#include <windows.h>\n" 610 "#include \"kbd.h\"\n" 611 "#include \"%s.h\"\n\n", 612 gKBDName); 613 } 614 615 /* What kind of driver is this? */ 616 if (FallbackDriver) 617 { 618 /* Only one section */ 619 fprintf(FileHandle, 620 "#pragma data_seg(\"%s\")\n#define ALLOC_SECTION_LDATA\n\n", 621 ".kbdfallback"); 622 } 623 else 624 { 625 /* Section and attributes depend on architecture */ 626 fprintf(FileHandle, 627 "#if defined(_M_IA64)\n" 628 "#pragma section(\"%s\")\n" 629 "#define ALLOC_SECTION_LDATA __declspec(allocate(\"%s\"))\n" 630 "#else\n" 631 "#pragma data_seg(\"%s\")\n" 632 "#define ALLOC_SECTION_LDATA\n" 633 "#endif\n\n", 634 ".data", 635 ".data", 636 ".data"); 637 } 638 639 /* Scan code to virtual key conversion table header */ 640 fprintf(FileHandle, 641 "/***************************************************************************\\\n" 642 "* ausVK[] - Virtual Scan Code to Virtual Key conversion table\n" 643 "\\***************************************************************************/\n\n"); 644 645 /* Table begin */ 646 fprintf(FileHandle, 647 "static ALLOC_SECTION_LDATA USHORT ausVK[] = {\n" 648 " T00, T01, T02, T03, T04, T05, T06, T07,\n" 649 " T08, T09, T0A, T0B, T0C, T0D, T0E, T0F,\n" 650 " T10, T11, T12, T13, T14, T15, T16, T17,\n" 651 " T18, T19, T1A, T1B, T1C, T1D, T1E, T1F,\n" 652 " T20, T21, T22, T23, T24, T25, T26, T27,\n" 653 " T28, T29, T2A, T2B, T2C, T2D, T2E, T2F,\n" 654 " T30, T31, T32, T33, T34, T35,\n\n"); 655 656 /* Table continue */ 657 fprintf(FileHandle, 658 " /*\n" 659 " * Right-hand Shift key must have KBDEXT bit set.\n" 660 " */\n" 661 " T36 | KBDEXT,\n\n" 662 " T37 | KBDMULTIVK, // numpad_* + Shift/Alt -> SnapShot\n\n" 663 " T38, T39, T3A, T3B, T3C, T3D, T3E,\n" 664 " T3F, T40, T41, T42, T43, T44,\n\n"); 665 666 /* Table continue */ 667 fprintf(FileHandle, 668 " /*\n" 669 " * NumLock Key:\n" 670 " * KBDEXT - VK_NUMLOCK is an Extended key\n" 671 " * KBDMULTIVK - VK_NUMLOCK or VK_PAUSE (without or with CTRL)\n" 672 " */\n" 673 " T45 | KBDEXT | KBDMULTIVK,\n\n" 674 " T46 | KBDMULTIVK,\n\n"); 675 676 /* Numpad table */ 677 fprintf(FileHandle, 678 " /*\n" 679 " * Number Pad keys:\n" 680 " * KBDNUMPAD - digits 0-9 and decimal point.\n" 681 " * KBDSPECIAL - require special processing by Windows\n" 682 " */\n" 683 " T47 | KBDNUMPAD | KBDSPECIAL, // Numpad 7 (Home)\n" 684 " T48 | KBDNUMPAD | KBDSPECIAL, // Numpad 8 (Up),\n" 685 " T49 | KBDNUMPAD | KBDSPECIAL, // Numpad 9 (PgUp),\n" 686 " T4A,\n" 687 " T4B | KBDNUMPAD | KBDSPECIAL, // Numpad 4 (Left),\n" 688 " T4C | KBDNUMPAD | KBDSPECIAL, // Numpad 5 (Clear),\n" 689 " T4D | KBDNUMPAD | KBDSPECIAL, // Numpad 6 (Right),\n" 690 " T4E,\n" 691 " T4F | KBDNUMPAD | KBDSPECIAL, // Numpad 1 (End),\n" 692 " T50 | KBDNUMPAD | KBDSPECIAL, // Numpad 2 (Down),\n" 693 " T51 | KBDNUMPAD | KBDSPECIAL, // Numpad 3 (PgDn),\n" 694 " T52 | KBDNUMPAD | KBDSPECIAL, // Numpad 0 (Ins),\n" 695 " T53 | KBDNUMPAD | KBDSPECIAL, // Numpad . (Del),\n\n"); 696 697 /* Table finish */ 698 fprintf(FileHandle, 699 " T54, T55, T56, T57, T58, T59, T5A, T5B,\n" 700 " T5C, T5D, T5E, T5F, T60, T61, T62, T63,\n" 701 " T64, T65, T66, T67, T68, T69, T6A, T6B,\n" 702 " T6C, T6D, T6E, T6F, T70, T71, T72, T73,\n" 703 " T74, T75, T76, T77, T78, T79, T7A, T7B,\n" 704 " T7C, T7D, T7E\n\n" 705 "};\n\n"); 706 707 /* Key name table header */ 708 fprintf(FileHandle, "static ALLOC_SECTION_LDATA VSC_VK aE0VscToVk[] = {\n"); 709 710 /* Loop 110-key table */ 711 for (i = 0; i < 110; i++) 712 { 713 /* Check for non-extended keys */ 714 if ((Layout->Entry[i].ScanCode & 0xFF00) == 0xE000) 715 { 716 /* Which are valid */ 717 if (Layout->Entry[i].ScanCode != 0xFF) 718 { 719 /* And mapped */ 720 if (Layout->Entry[i].VirtualKey != 0xFF) 721 { 722 /* Output them */ 723 fprintf(FileHandle, 724 " { 0x%02X, X%02X | KBDEXT }, // %s\n", 725 Layout->Entry[i].ScanCode, 726 Layout->Entry[i].ScanCode, 727 Layout->Entry[i].Name); 728 } 729 } 730 } 731 } 732 733 /* Key name table finish */ 734 fprintf(FileHandle, " { 0, 0 }\n};\n\n"); 735 736 /* Extended key name table header */ 737 fprintf(FileHandle, "static ALLOC_SECTION_LDATA VSC_VK aE1VscToVk[] = {\n"); 738 739 /* Loop 110-key table */ 740 for (i = 0; i < 110; i++) 741 { 742 /* Check for extended keys */ 743 if ((Layout->Entry[i].ScanCode & 0xFF00) == 0xE100) 744 { 745 /* Which are valid */ 746 if (Layout->Entry[i].ScanCode != 0xFF) 747 { 748 /* And mapped */ 749 if (Layout->Entry[i].VirtualKey != 0xFF) 750 { 751 /* Output them */ 752 fprintf(FileHandle, 753 " { 0x%02X, Y%02X | KBDEXT }, // %s\n", 754 Layout->Entry[i].ScanCode, 755 Layout->Entry[i].ScanCode, 756 Layout->Entry[i].Name); 757 } 758 } 759 } 760 } 761 762 /* Extended key name table finish */ 763 fprintf(FileHandle, 764 " { 0x1D, Y1D }, // Pause\n" 765 " { 0 , 0 }\n};\n\n"); 766 767 /* Modifier table description */ 768 fprintf(FileHandle, 769 "/***************************************************************************\\\n" 770 "* aVkToBits[] - map Virtual Keys to Modifier Bits\n" 771 "*\n" 772 "* See kbd.h for a full description.\n" 773 "*\n" 774 "* The keyboard has only three shifter keys:\n" 775 "* SHIFT (L & R) affects alphabnumeric keys,\n" 776 "* CTRL (L & R) is used to generate control characters\n" 777 "* ALT (L & R) used for generating characters by number with numpad\n" 778 "\\***************************************************************************/\n"); 779 780 /* Modifier table header */ 781 fprintf(FileHandle, "static ALLOC_SECTION_LDATA VK_TO_BIT aVkToBits[] = {\n"); 782 783 /* Loop modifier table */ 784 i = 0; 785 Entry = &Modifiers[0]; 786 while (Entry->VirtualKey) 787 { 788 /* Print out entry */ 789 fprintf(FileHandle, 790 " { %-12s, %-12s },\n", 791 getVKName(Entry->VirtualKey, 1), 792 Entry->Name); 793 794 /* Move to the next one */ 795 Entry = &Modifiers[++i]; 796 } 797 798 /* Modifier table finish */ 799 fprintf(FileHandle, " { 0, 0 }\n};\n\n"); 800 801 /* Modifier conversion table description */ 802 fprintf(FileHandle, 803 "/***************************************************************************\\\n" 804 "* aModification[] - map character modifier bits to modification number\n" 805 "*\n" 806 "* See kbd.h for a full description.\n" 807 "*\n" 808 "\\***************************************************************************/\n\n"); 809 810 /* Zero out local state data */ 811 for (i = 0; i < 8; i++) States[i] = -1; 812 813 /* Find the highest set state */ 814 for (HighestState = 1, i = 0; (i < 8) && (ShiftStates[i] != -1); i++) 815 { 816 /* Save all state values */ 817 States[ShiftStates[i]] = i; 818 if (ShiftStates[i] > HighestState) HighestState = ShiftStates[i]; 819 } 820 821 /* Modifier conversion table header */ 822 fprintf(FileHandle, 823 "static ALLOC_SECTION_LDATA MODIFIERS CharModifiers = {\n" 824 " &aVkToBits[0],\n" 825 " %d,\n" 826 " {\n" 827 " // Modification# // Keys Pressed\n" 828 " // ============= // =============\n", 829 HighestState); 830 831 /* Loop states */ 832 for (i = 0; i <= HighestState; i++) 833 { 834 /* Check for invalid state */ 835 if (States[i] == -1) 836 { 837 /* Invalid state header */ 838 fprintf(FileHandle, " SHFT_INVALID, // "); 839 } 840 else 841 { 842 /* Is this the last one? */ 843 if (i == HighestState) 844 { 845 /* Last state header */ 846 fprintf(FileHandle, " %d // ", States[i]); 847 } 848 else 849 { 850 /* Normal state header */ 851 fprintf(FileHandle, " %d, // ", States[i]); 852 } 853 854 /* State 1 or higher? */ 855 if (i >= 1) 856 { 857 /* J is the loop variable, K is the double */ 858 for (NeedPlus = 0, j = 0, k = 1; (1u << j) <= i; j++, k = (1 << j)) 859 { 860 /* Do we need to add a plus? */ 861 if (NeedPlus) 862 { 863 /* Add it */ 864 fprintf(FileHandle, "+"); 865 NeedPlus = FALSE; 866 } 867 868 /* Check if it's time to add a modifier */ 869 if (i & k) 870 { 871 /* Get the key state name and copy it into our buffer */ 872 strcpy(KeyNameBuffer, getVKName(Modifiers[j].VirtualKey, 1)); 873 874 /* Go go the 4th char (past the "KBD") and lower name */ 875 for (p = &KeyNameBuffer[4]; *p; p++) *p = tolower(*p); 876 877 /* Print it */ 878 fprintf(FileHandle, "%s", &KeyNameBuffer[3]); 879 880 /* We'll need a plus sign next */ 881 NeedPlus = TRUE; 882 } 883 } 884 } 885 886 /* Terminate the entry */ 887 fprintf(FileHandle, "\n"); 888 } 889 } 890 891 892 /* Modifier conversion table end */ 893 fprintf(FileHandle," }\n" "};\n\n"); 894 895 /* Shift state translation table description */ 896 fprintf(FileHandle, 897 "/***************************************************************************\\\n" 898 "*\n" 899 "* aVkToWch2[] - Virtual Key to WCHAR translation for 2 shift states\n" 900 "* aVkToWch3[] - Virtual Key to WCHAR translation for 3 shift states\n" 901 "* aVkToWch4[] - Virtual Key to WCHAR translation for 4 shift states\n"); 902 903 /* Check if there's exta shift states */ 904 for (i = 5; i < HighestState; i++) 905 { 906 /* Print out extra information */ 907 fprintf(FileHandle, 908 "* aVkToWch%d[] - Virtual Key to WCHAR translation for %d shift states\n", 909 i, 910 i); 911 } 912 913 /* Shift state translation table description continue */ 914 fprintf(FileHandle, 915 "*\n" 916 "* Table attributes: Unordered Scan, null-terminated\n" 917 "*\n" 918 "* Search this table for an entry with a matching Virtual Key to find the\n" 919 "* corresponding unshifted and shifted WCHAR characters.\n" 920 "*\n" 921 "* Special values for VirtualKey (column 1)\n" 922 "* 0xff - dead chars for the previous entry\n" 923 "* 0 - terminate the list\n" 924 "*\n" 925 "* Special values for Attributes (column 2)\n" 926 "* CAPLOK bit - CAPS-LOCK affect this key like SHIFT\n" 927 "*\n" 928 "* Special values for wch[*] (column 3 & 4)\n" 929 "* WCH_NONE - No character\n" 930 "* WCH_DEAD - Dead Key (diaresis) or invalid (US keyboard has none)\n" 931 "* WCH_LGTR - Ligature (generates multiple characters)\n" 932 "*\n" 933 "\\***************************************************************************/\n\n"); 934 935 /* Loop all the states */ 936 for (i = 2; i <= StateCount; i++) 937 { 938 /* Check if this something else than state 2 */ 939 if (i != 2) 940 { 941 /* Loop all the scan codes */ 942 for (j = 0; j < 110; j++) 943 { 944 /* Check if this is the state for the entry */ 945 if (i == Layout->Entry[j].StateCount) break; 946 } 947 } 948 949 /* Print the table header */ 950 fprintf(FileHandle, 951 "static ALLOC_SECTION_LDATA VK_TO_WCHARS%d aVkToWch%d[] = {\n" 952 "// | | Shift |", 953 i, 954 i); 955 956 /* Print the correct state label */ 957 for (k = 2; k < i; k++) fprintf(FileHandle, "%-9.9s|", 958 StateLabel[ShiftStates[k]]); 959 960 /* Print the next separator */ 961 fprintf(FileHandle, "\n// |=========|=========|"); 962 963 /* Check for extra states and print their separators too */ 964 for (k = 2; k < i; k++) fprintf(FileHandle, "=========|"); 965 966 /* Finalize the separator header */ 967 fprintf(FileHandle, "\n"); 968 969 /* Loop all the scan codes */ 970 for (j = 0; j < 110; j++) 971 { 972 /* Check if this is the state for the entry */ 973 if (i != Layout->Entry[j].StateCount) continue; 974 975 /* Print out the entry for this key */ 976 fprintf(FileHandle, 977 " {%-13s,%-7s", 978 getVKName(Layout->Entry[j].VirtualKey, 1), 979 CapState[Layout->Entry[j].Cap]); 980 981 /* Initialize the buffer for this line */ 982 *LineBuffer = '\0'; 983 984 /* Loop states */ 985 for (k = 0; k < i; k++) 986 { 987 /* Check for dead key data */ 988 if (DeadKeyData) 989 { 990 /* Not yet supported */ 991 printf("Dead key data not supported!\n"); 992 exit(1); 993 } 994 995 /* Check if it's a ligature key */ 996 if (Layout->Entry[j].LigatureCharData[k]) 997 { 998 /* Not yet supported */ 999 printf("Ligature key data not supported!\n"); 1000 exit(1); 1001 } 1002 1003 /* Print out the WCH_ name */ 1004 fprintf(FileHandle, 1005 ",%-9s", 1006 WChName(Layout->Entry[j].CharData[k], 0)); 1007 1008 /* If we have something on the line buffer by now, add WCH_NONE */ 1009 if (*LineBuffer != '\0') strcpy(LineBuffer, "WCH_NONE "); 1010 } 1011 1012 /* Finish the line */ 1013 fprintf(FileHandle, "},\n"); 1014 1015 /* Do we have any data at all? */ 1016 if (*LineBuffer != '\0') 1017 { 1018 /* Print it, we're done */ 1019 fprintf(FileHandle, "%s},\n", LineBuffer); 1020 continue; 1021 } 1022 1023 /* Otherwise, we're done, unless this requires SGCAP data */ 1024 if (Layout->Entry[j].Cap != 2) continue; 1025 1026 /* Not yet supported */ 1027 printf("SGCAP not yet supported!\n"); 1028 exit(1); 1029 } 1030 1031 /* Did we only have two states? */ 1032 if (i == 2) 1033 { 1034 /* Print out the built-in table */ 1035 fprintf(FileHandle, 1036 " {VK_TAB ,0 ,'\\t' ,'\\t' },\n" 1037 " {VK_ADD ,0 ,'+' ,'+' },\n" 1038 " {VK_DIVIDE ,0 ,'/' ,'/' },\n" 1039 " {VK_MULTIPLY ,0 ,'*' ,'*' },\n" 1040 " {VK_SUBTRACT ,0 ,'-' ,'-' },\n"); 1041 } 1042 1043 /* Terminate the table */ 1044 fprintf(FileHandle, " {0 ,0 "); 1045 for (k = 0; k < i; k++) fprintf(FileHandle, ",0 "); 1046 1047 /* Terminate the structure */ 1048 fprintf(FileHandle, "}\n" "};\n\n"); 1049 } 1050 1051 /* Numpad translation table */ 1052 fprintf(FileHandle, 1053 "// Put this last so that VkKeyScan interprets number characters\n" 1054 "// as coming from the main section of the kbd (aVkToWch2 and\n" 1055 "// aVkToWch5) before considering the numpad (aVkToWch1).\n\n" 1056 "static ALLOC_SECTION_LDATA VK_TO_WCHARS1 aVkToWch1[] = {\n" 1057 " { VK_NUMPAD0 , 0 , '0' },\n" 1058 " { VK_NUMPAD1 , 0 , '1' },\n" 1059 " { VK_NUMPAD2 , 0 , '2' },\n" 1060 " { VK_NUMPAD3 , 0 , '3' },\n" 1061 " { VK_NUMPAD4 , 0 , '4' },\n" 1062 " { VK_NUMPAD5 , 0 , '5' },\n" 1063 " { VK_NUMPAD6 , 0 , '6' },\n" 1064 " { VK_NUMPAD7 , 0 , '7' },\n" 1065 " { VK_NUMPAD8 , 0 , '8' },\n" 1066 " { VK_NUMPAD9 , 0 , '9' },\n" 1067 " { 0 , 0 , '\\0' }\n" 1068 "};\n\n"); 1069 1070 /* Translation tables header */ 1071 fprintf(FileHandle,"static ALLOC_SECTION_LDATA VK_TO_WCHAR_TABLE aVkToWcharTable[] = {\n"); 1072 1073 /* Loop states higher than 3 */ 1074 for (i = 3; i <= StateCount; i++) 1075 { 1076 /* Print out the extra tables */ 1077 fprintf(FileHandle, 1078 " { (PVK_TO_WCHARS1)aVkToWch%d, %d, sizeof(aVkToWch%d[0]) },\n", 1079 i, 1080 i, 1081 i); 1082 } 1083 1084 /* Array of translation tables */ 1085 fprintf(FileHandle, 1086 " { (PVK_TO_WCHARS1)aVkToWch2, 2, sizeof(aVkToWch2[0]) },\n" 1087 " { (PVK_TO_WCHARS1)aVkToWch1, 1, sizeof(aVkToWch1[0]) },\n" 1088 " { NULL, 0, 0 },\n" 1089 "};\n\n"); 1090 1091 /* Scan code to key name conversion table description */ 1092 fprintf(FileHandle, 1093 "/***************************************************************************\\\n" 1094 "* aKeyNames[], aKeyNamesExt[] - Virtual Scancode to Key Name tables\n" 1095 "*\n" 1096 "* Table attributes: Ordered Scan (by scancode), null-terminated\n" 1097 "*\n" 1098 "* Only the names of Extended, NumPad, Dead and Non-Printable keys are here.\n" 1099 "* (Keys producing printable characters are named by that character)\n" 1100 "\\***************************************************************************/\n\n"); 1101 1102 /* Check for key name data */ 1103 if (KeyNameData) 1104 { 1105 /* Table header */ 1106 fprintf(FileHandle, "static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNames[] = {\n"); 1107 1108 /* Print table */ 1109 PrintNameTable(FileHandle, KeyNameData, FALSE); 1110 1111 /* Table end */ 1112 fprintf(FileHandle, "};\n\n"); 1113 } 1114 1115 /* Check for extended key name data */ 1116 if (KeyNameExtData) 1117 { 1118 /* Table header */ 1119 fprintf(FileHandle, "static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNamesExt[] = {\n"); 1120 1121 /* Print table */ 1122 PrintNameTable(FileHandle, KeyNameExtData, FALSE); 1123 1124 /* Table end */ 1125 fprintf(FileHandle, "};\n\n"); 1126 } 1127 1128 /* Check for dead key name data */ 1129 if (KeyNameDeadData) 1130 { 1131 /* Not yet supported */ 1132 printf("Dead key name data not supported!\n"); 1133 exit(1); 1134 } 1135 1136 /* Check for dead key data */ 1137 if (DeadKeyData) 1138 { 1139 /* Not yet supported */ 1140 printf("Dead key data not supported!\n"); 1141 exit(1); 1142 } 1143 1144 /* Check for ligature data */ 1145 if (LigatureData) 1146 { 1147 /* Not yet supported */ 1148 printf("Ligature key data not supported!\n"); 1149 exit(1); 1150 } 1151 1152 /* Main keyboard table descriptor type */ 1153 fprintf(FileHandle, "static "); 1154 1155 /* FIXME? */ 1156 1157 /* Main keyboard table descriptor header */ 1158 fprintf(FileHandle, 1159 "ALLOC_SECTION_LDATA KBDTABLES KbdTables%s = {\n" 1160 " /*\n" 1161 " * Modifier keys\n" 1162 " */\n" 1163 " &CharModifiers,\n\n" 1164 " /*\n" 1165 " * Characters tables\n" 1166 " */\n" 1167 " aVkToWcharTable,\n\n" 1168 " /*\n" 1169 " * Diacritics\n" 1170 " */\n", 1171 FallbackDriver ? "Fallback" : "" ); 1172 1173 /* Descriptor dead key data section */ 1174 if (DeadKeyData) 1175 { 1176 fprintf(FileHandle, " aDeadKey,\n\n"); 1177 } 1178 else 1179 { 1180 fprintf(FileHandle, " NULL,\n\n"); 1181 } 1182 1183 /* Descriptor key name comment */ 1184 fprintf(FileHandle, 1185 " /*\n" 1186 " * Names of Keys\n" 1187 " */\n"); 1188 1189 /* Descriptor key name section */ 1190 if (KeyNameData) 1191 { 1192 fprintf(FileHandle, " aKeyNames,\n"); 1193 } 1194 else 1195 { 1196 fprintf(FileHandle, " NULL,\n"); 1197 } 1198 1199 /* Descriptor extended key name section */ 1200 if (KeyNameExtData) 1201 { 1202 fprintf(FileHandle, " aKeyNamesExt,\n"); 1203 } 1204 else 1205 { 1206 fprintf(FileHandle, " NULL,\n"); 1207 } 1208 1209 /* Descriptor dead key name section */ 1210 if ((DeadKeyData) && (KeyNameDeadData)) 1211 { 1212 fprintf(FileHandle, " aKeyNamesDead,\n\n"); 1213 } 1214 else 1215 { 1216 fprintf(FileHandle, " NULL,\n\n"); 1217 } 1218 1219 /* Descriptor conversion table section */ 1220 fprintf(FileHandle, 1221 " /*\n" 1222 " * Scan codes to Virtual Keys\n" 1223 " */\n" 1224 " ausVK,\n" 1225 " sizeof(ausVK) / sizeof(ausVK[0]),\n" 1226 " aE0VscToVk,\n" 1227 " aE1VscToVk,\n\n" 1228 " /*\n" 1229 " * Locale-specific special processing\n" 1230 " */\n"); 1231 1232 /* FIXME: AttributeData and KLLF_ALTGR stuff */ 1233 1234 /* Descriptor locale-specific section */ 1235 fprintf(FileHandle, " MAKELONG(%s, KBD_VERSION),\n\n", "0"); /* FIXME */ 1236 1237 /* Descriptor ligature data comment */ 1238 fprintf(FileHandle, " /*\n * Ligatures\n */\n %d,\n", 0); /* FIXME */ 1239 1240 /* Descriptor ligature data section */ 1241 if (!LigatureData) 1242 { 1243 fprintf(FileHandle, " 0,\n"); 1244 fprintf(FileHandle, " NULL\n"); 1245 } 1246 else 1247 { 1248 fprintf(FileHandle, " sizeof(aLigature[0]),\n"); 1249 fprintf(FileHandle, " (PLIGATURE1)aLigature\n"); 1250 } 1251 1252 /* Descriptor finish */ 1253 fprintf(FileHandle, "};\n\n"); 1254 1255 /* Keyboard layout callback function */ 1256 if (!FallbackDriver) fprintf(FileHandle, 1257 "PKBDTABLES KbdLayerDescriptor(VOID)\n" 1258 "{\n" 1259 " return &KbdTables;\n" 1260 "}\n"); 1261 1262 /* Clean up */ 1263 fclose(FileHandle); 1264 return TRUE; 1265 } 1266 1267 ULONG 1268 DoOutput(IN ULONG StateCount, 1269 IN PULONG ShiftStates, 1270 IN PKEYNAME DescriptionData, 1271 IN PKEYNAME LanguageData, 1272 IN PVOID AttributeData, 1273 IN PVOID DeadKeyData, 1274 IN PVOID LigatureData, 1275 IN PKEYNAME KeyNameData, 1276 IN PKEYNAME KeyNameExtData, 1277 IN PKEYNAME KeyNameDeadData) 1278 { 1279 ULONG FailureCode = 0; 1280 1281 /* Take the time */ 1282 time(&Clock); 1283 Now = localtime(&Clock); 1284 1285 /* Check if this just a fallback driver*/ 1286 if (!FallbackDriver) 1287 { 1288 /* It's not, create header file */ 1289 if (!kbd_h(&g_Layout)) FailureCode = 1; 1290 1291 /* Create the resource file */ 1292 if (!kbd_rc(DescriptionData, LanguageData)) FailureCode = 2; 1293 } 1294 1295 /* Create the C file */ 1296 if (!kbd_c(StateCount, 1297 ShiftStates, 1298 AttributeData, 1299 &g_Layout, 1300 DeadKeyData, 1301 LigatureData, 1302 KeyNameData, 1303 KeyNameExtData, 1304 KeyNameDeadData)) 1305 { 1306 /* Failed in C file generation */ 1307 FailureCode = 3; 1308 } 1309 1310 /* Check if this just a fallback driver*/ 1311 if (!FallbackDriver) 1312 { 1313 /* Generate the definition file */ 1314 if (!kbd_def()) FailureCode = 4; 1315 } 1316 1317 /* Done */ 1318 return FailureCode; 1319 } 1320 1321 1322 /* EOF */ 1323