[CRT] Massively improve performance of rand_s
[reactos.git] / sdk / tools / kbdtool / output.c
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 */