Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2856 lines
87 KiB

  1. /******************************* Module Header *******************************\
  2. * Module Name: KBDTXT2C.C
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation
  5. *
  6. * History:
  7. * 1995-03-26 a-KChang
  8. * 1997-06-13 GregoryW v2.00 BiDi Support
  9. * 1997-06-19 IanJa v2.01 Add ATTRIBUTES section
  10. * 1998-03-04 IanJa v3.0 Add dead key composition can be dead char too
  11. * (Useful for CAN/CSA, Serge Caron @ Attachmate
  12. * and a customer of Eliyas Yakub's)
  13. * 1998-05-01 HiroYama v3.01 -k switch to make fallback layout for win32k.sys
  14. * 1998-05-08 IanJa v3.02 new E1 scancodes allowed
  15. * 1998-05-19 v-thief v3.03 Add IA64 support. Implies that the data arrays
  16. * are located in the long data section.
  17. * Uses IA64 compiler specific pragmas.
  18. * data_seg() is not explicit enough.
  19. * 1998-05-20 v-thief v3.04 For the fallback layout in win32k.sys, we are
  20. * not relocating the data in long data section.
  21. * 1998-10-29 WKwok v3.05 Specify VER_LANGNEUTRAL in RC.
  22. * 1998-12-03 IanJa v3.06 Add SpeedRacer VKs, include strid.h
  23. * 1999-01-12 IanJa v3.07 check for dup VKs, beautify, improve VkKeyScan
  24. * 1999-01-28 v-thief v3.08 fixed IA64 warnings for .data section. The new
  25. * IA64 compiler defaults to a "long" attribute
  26. * for this known section.
  27. * 1999-02-11 IanJa v3.09 check for dup chars (for VkKeyScanEx's sake)
  28. * 1999-03-25 IanJa v3.10 no more vkoem.h (get VKs from winuser.h)
  29. * 1999-03-31 IanJa v3.11 comment out spurious DumpLayoutEntry() call
  30. * 2001-06-28 Hiroyama v3.12 fix the upper case warnings etc..
  31. putting the sanity check in "-W".
  32. \*****************************************************************************/
  33. #include <windows.h>
  34. #include <winuserp.h>
  35. #include "kbdx.h"
  36. DWORD gVersion = 3;
  37. DWORD gSubVersion = 12;
  38. char *KeyWord[] = { /* used by isKeyWord() */
  39. "KBD", /* 0 */
  40. "VERSION", /* 1 */
  41. "MODIFIERS", /* 2 */
  42. "SHIFTSTATE", /* 3 */
  43. "ATTRIBUTES", /* 4 */
  44. "LAYOUT", /* 5 */
  45. "DEADKEY", /* 6 */
  46. "LIGATURE", /* 7 */
  47. "KEYNAME", /* 8 */
  48. "KEYNAME_EXT", /* 9 */
  49. "KEYNAME_DEAD", /* 10 */
  50. "ENDKBD", /* 11 */
  51. };
  52. #define KEYWORD_KBD 0
  53. #define KEYWORD_VERSION 1
  54. #define KEYWORD_MODIFIERS 2
  55. #define KEYWORD_SHIFTSTATE 3
  56. #define KEYWORD_ATTRIBUTES 4
  57. #define KEYWORD_LAYOUT 5
  58. #define KEYWORD_DEADKEY 6
  59. #define KEYWORD_LIGATURE 7
  60. #define KEYWORD_KEYNAME 8
  61. #define KEYWORD_KEYNAME_EXT 9
  62. #define KEYWORD_KEYNAME_DEAD 10
  63. #define KEYWORD_ENDKBD 11
  64. #define NUMKEYWORD ( sizeof(KeyWord) / sizeof(char*) )
  65. #define NOT_KEYWORD 999 /* a number bigger than NUMKEYWORD */
  66. #define DEADKEYCODE 6 /* only DEADKEY can have multiple entries */
  67. VKEYNAME VKName[] = { /* used only by virtual keys other than 0-9 and A-Z */
  68. {VK_BACK, "BACK" },
  69. {VK_CANCEL, "CANCEL" },
  70. {VK_ESCAPE, "ESCAPE" },
  71. {VK_RETURN, "RETURN" },
  72. {VK_SPACE, "SPACE" },
  73. {VK_DECIMAL, "DECIMAL" },
  74. {VK_OEM_1, "OEM_1" },
  75. {VK_OEM_PLUS, "OEM_PLUS" },
  76. {VK_OEM_COMMA, "OEM_COMMA" },
  77. {VK_OEM_MINUS, "OEM_MINUS" },
  78. {VK_OEM_PERIOD, "OEM_PERIOD" },
  79. {VK_OEM_2, "OEM_2" },
  80. {VK_OEM_3, "OEM_3" },
  81. {VK_OEM_4, "OEM_4" },
  82. {VK_OEM_5, "OEM_5" },
  83. {VK_OEM_6, "OEM_6" },
  84. {VK_OEM_7, "OEM_7" },
  85. {VK_OEM_8, "OEM_8" },
  86. {VK_OEM_102, "OEM_102" },
  87. {0xC1, "ABNT_C1" },
  88. {0xC2, "ABNT_C2" },
  89. {VK_SHIFT, "SHIFT" },
  90. {VK_LSHIFT, "LSHIFT" },
  91. {VK_RSHIFT, "RSHIFT" },
  92. {VK_MENU, "MENU" },
  93. {VK_LMENU, "LMENU" },
  94. {VK_RMENU, "RMENU" },
  95. {VK_CONTROL, "CONTROL" },
  96. {VK_LCONTROL, "LCONTROL" },
  97. {VK_RCONTROL, "RCONTROL" },
  98. {VK_SEPARATOR, "SEPARATOR" },
  99. {VK_ICO_00, "ICO_00" },
  100. {VK_DELETE, "DELETE" },
  101. {VK_INSERT, "INSERT" },
  102. {VK_GROUPSHIFT, "GROUPSHIFT" },
  103. {VK_RGROUPSHIFT,"RGROUPSHIFT"},
  104. };
  105. #define NUMVKNAME ( sizeof(VKName) / sizeof(VKEYNAME) )
  106. /*
  107. * Default ScanCode-VirtualKey relation
  108. *
  109. * Includes a comment string used only for E0 prefixed scancodes and
  110. * then only as a comment for aE0VscToVk[] entries in the output .C file
  111. *
  112. * This does not have to be ordered by scancode or virtual key code.
  113. * The order *does* affect VkKeyScan[Ex] - each aVkToWch*[] table is
  114. * ordered according to the order of the entries in this table.
  115. *
  116. *
  117. * Scan VKey comment
  118. * ==== ========= =======
  119. */
  120. SC_VK ScVk[] = {
  121. {0x02, 0x31, NULL}, /* 1 */
  122. {0x03, 0x32, NULL}, /* 2 */
  123. {0x04, 0x33, NULL}, /* 3 */
  124. {0x05, 0x34, NULL}, /* 4 */
  125. {0x06, 0x35, NULL}, /* 5 */
  126. {0x07, 0x36, NULL}, /* 6 */
  127. {0x08, 0x37, NULL}, /* 7 */
  128. {0x09, 0x38, NULL}, /* 8 */
  129. {0x0a, 0x39, NULL}, /* 9 */
  130. {0x0b, 0x30, NULL}, /* 0 */
  131. {0x0c, 0xbd, NULL}, /* OEM_MINUS */
  132. {0x0d, 0xbb, NULL}, /* OEM_PLUS */
  133. {0x10, 0x51, NULL}, /* Q */
  134. {0x11, 0x57, NULL}, /* W */
  135. {0x12, 0x45, NULL}, /* E */
  136. {0x13, 0x52, NULL}, /* R */
  137. {0x14, 0x54, NULL}, /* T */
  138. {0x15, 0x59, NULL}, /* Y */
  139. {0x16, 0x55, NULL}, /* U */
  140. {0x17, 0x49, NULL}, /* I */
  141. {0x18, 0x4f, NULL}, /* O */
  142. {0x19, 0x50, NULL}, /* P */
  143. {0x1a, 0xdb, NULL}, /* OEM_4 */
  144. {0x1b, 0xdd, NULL}, /* OEM_6 */
  145. {0x1e, 0x41, NULL}, /* A */
  146. {0x1f, 0x53, NULL}, /* S */
  147. {0x20, 0x44, NULL}, /* D */
  148. {0x21, 0x46, NULL}, /* F */
  149. {0x22, 0x47, NULL}, /* G */
  150. {0x23, 0x48, NULL}, /* H */
  151. {0x24, 0x4a, NULL}, /* J */
  152. {0x25, 0x4b, NULL}, /* K */
  153. {0x26, 0x4c, NULL}, /* L */
  154. {0x27, 0xba, NULL}, /* OEM_1 */
  155. {0x28, 0xde, NULL}, /* OEM_7 */
  156. {0x29, 0xc0, NULL}, /* OEM_3 */
  157. {0x2b, 0xdc, NULL}, /* OEM_5 */
  158. {0x2c, 0x5a, NULL}, /* Z */
  159. {0x2d, 0x58, NULL}, /* X */
  160. {0x2e, 0x43, NULL}, /* C */
  161. {0x2f, 0x56, NULL}, /* V */
  162. {0x30, 0x42, NULL}, /* B */
  163. {0x31, 0x4e, NULL}, /* N */
  164. {0x32, 0x4d, NULL}, /* M */
  165. {0x33, 0xbc, NULL}, /* OEM_COMMA */
  166. {0x34, 0xbe, NULL}, /* OEM_PERIOD */
  167. {0x35, 0xbf, NULL}, /* OEM_2 */
  168. {0x56, 0xe2, NULL}, /* OEM_102 */
  169. {0x73, 0xc1, NULL}, /* ABNT_C1 */
  170. {0x7e, 0xc2, NULL}, /* ABNT_C2 */
  171. // extended scancodes
  172. // The comment is only as a comment for aE0VscToVk[] entries
  173. // in the output .C file
  174. {0xE010, VK_MEDIA_PREV_TRACK, "Speedracer: Previous Track" },
  175. {0xE019, VK_MEDIA_NEXT_TRACK, "Speedracer: Next Track" },
  176. {0xE01D, VK_RCONTROL , "RControl" },
  177. {0xE020, VK_VOLUME_MUTE , "Speedracer: Volume Mute" },
  178. {0xE021, VK_LAUNCH_APP2 , "Speedracer: Launch App 2" },
  179. {0xE022, VK_MEDIA_PLAY_PAUSE, "Speedracer: Media Play/Pause" },
  180. {0xE024, VK_MEDIA_STOP , "Speedracer: Media Stop" },
  181. {0xE02E, VK_VOLUME_DOWN , "Speedracer: Volume Down" },
  182. {0xE030, VK_VOLUME_UP , "Speedracer: Volume Up" },
  183. {0xE032, VK_BROWSER_HOME , "Speedracer: Browser Home" },
  184. {0xE035, VK_DIVIDE , "Numpad Divide" },
  185. {0xE037, VK_SNAPSHOT , "Snapshot" },
  186. {0xE038, VK_RMENU , "RMenu" },
  187. {0xE047, VK_HOME , "Home" },
  188. {0xE048, VK_UP , "Up" },
  189. {0xE049, VK_PRIOR , "Prior" },
  190. {0xE04B, VK_LEFT , "Left" },
  191. {0xE04D, VK_RIGHT , "Right" },
  192. {0xE04F, VK_END , "End" },
  193. {0xE050, VK_DOWN , "Down" },
  194. {0xE051, VK_NEXT , "Next" },
  195. {0xE052, VK_INSERT , "Insert" },
  196. {0xE053, VK_DELETE , "Delete" },
  197. {0xE05B, VK_LWIN , "Left Win" },
  198. {0xE05C, VK_RWIN , "Right Win" },
  199. {0xE05D, VK_APPS , "Application" },
  200. // reserved (VKey == 0xff)
  201. {0xE05E, 0xff , "Power" },
  202. {0xE05F, VK_SLEEP , "Speedracer: Sleep" },
  203. {0xE060, 0xff , "BAD SCANCODE" }, // break would be 0xE0
  204. {0xE061, 0xff , "BAD SCANCODE" }, // break would be 0xE1
  205. // available for adding extended scancodes (VKey == 0x00)
  206. {0xE065, VK_BROWSER_SEARCH , "Speedracer: Browser Search" },
  207. {0xE066, VK_BROWSER_FAVORITES , "Speedracer: Browser Favorites" },
  208. {0xE067, VK_BROWSER_REFRESH , "Speedracer: Browser Refresh" },
  209. {0xE068, VK_BROWSER_STOP , "Speedracer: Browser Stop" },
  210. {0xE069, VK_BROWSER_FORWARD , "Speedracer: Browser Forward" },
  211. {0xE06A, VK_BROWSER_BACK , "Speedracer: Browser Back" },
  212. {0xE06B, VK_LAUNCH_APP1 , "Speedracer: Launch App 1" },
  213. {0xE06C, VK_LAUNCH_MAIL , "Speedracer: Launch Mail" },
  214. {0xE06D, VK_LAUNCH_MEDIA_SELECT, "Speedracer: Launch Media Selector"},
  215. // These come near the end for VkKeyScan...
  216. {0x53, VK_DECIMAL, NULL }, /* Numpad Decimal */
  217. {0x0e, VK_BACK, NULL }, /* Backspace */
  218. {0x01, VK_ESCAPE, NULL }, /* Escape */
  219. {0xE01C, VK_RETURN, "Numpad Enter" },
  220. {0x1c, VK_RETURN, NULL }, /* Enter */
  221. {0x39, VK_SPACE, NULL }, /* Space */
  222. {0xE046, VK_CANCEL, "Break (Ctrl + Pause)" },
  223. // ...but the 0xffff entries (for new scancodes) must come last
  224. {0xffff, 0x00, NULL },
  225. {0xffff, 0x00, NULL },
  226. {0xffff, 0x00, NULL },
  227. {0xffff, 0x00, NULL },
  228. {0xffff, 0x00, NULL },
  229. {0xffff, 0x00, NULL },
  230. {0xffff, 0x00, NULL },
  231. {0xffff, 0x00, NULL },
  232. {0xffff, 0x00, NULL },
  233. {0xffff, 0x00, NULL },
  234. {0xffff, 0x00, NULL },
  235. {0xffff, 0x00, NULL },
  236. {0xffff, 0x00, NULL },
  237. {0xffff, 0x00, NULL },
  238. };
  239. #define NUMSCVK ( sizeof(ScVk) / sizeof(SC_VK) )
  240. typedef struct {
  241. UINT Vk;
  242. char *pszModBits;
  243. } MODIFIERS, *PMODIFIERS;
  244. MODIFIERS Modifiers[] = {
  245. { VK_SHIFT, "KBDSHIFT" },
  246. { VK_CONTROL, "KBDCTRL" },
  247. { VK_MENU, "KBDALT" },
  248. { 0, NULL },
  249. { 0, NULL },
  250. { 0, NULL },
  251. { 0, NULL },
  252. { 0, NULL },
  253. { 0, NULL },
  254. { 0, NULL },
  255. { 0, NULL },
  256. { 0, NULL }
  257. };
  258. char* StateLabel[] = {
  259. "", /* 0 */
  260. "Shift", /* 1 */
  261. " Ctrl", /* 2 */
  262. "S+Ctrl", /* 3 */
  263. " Alt", /* 4:not used */
  264. "Shift+Alt", /* 5:not used */
  265. " Ctl+Alt", /* 6 */
  266. "S+Ctl+Alt", /* 7 */
  267. " X1 ", /* 8 */
  268. "S+ X1 ", /* 9 */
  269. " C+ X1 ", /* 10 */
  270. "S+C+ X1 ", /* 11 */
  271. " A+X1 ", /* 12 */
  272. "S+ A+X1 ", /* 13 */
  273. " C+A+X1 ", /* 14 */
  274. "S+C+A+X1 ", /* 15 */
  275. " X2", /* 16 */
  276. "S+ X2", /* 17 */
  277. " C+ X2", /* 18 */
  278. "S+C+ X2", /* 19 */
  279. " A+ X2", /* 20 */
  280. "S+ A+ X2", /* 21 */
  281. " C+A+ X2", /* 22 */
  282. "S+C+A+ X2", /* 23 */
  283. " X1+X2", /* 24 */
  284. "S+ X1+X2", /* 25 */
  285. " C+ X1+X2", /* 26 */
  286. "S+C+ X1+X2", /* 27 */
  287. " A+X1+X2", /* 28 */
  288. "S+ A+X1+X2", /* 29 */
  289. " C+A+X1+X2", /* 30 */
  290. "S+C+A+X1+X2", /* 31 */
  291. " X3", /* 32 */
  292. "S+ X3", /* 33 */
  293. " C+ X3", /* 34 */
  294. "S+C+ X3", /* 35 */
  295. " A+ X3", /* 36 */
  296. "S+ A+ X3", /* 37 */
  297. " C+A+ X3", /* 38 */
  298. "S+C+A+ X3", /* 39 */
  299. " X1+ X3", /* 40 */
  300. "S+ X1+ X3", /* 41 */
  301. " C+ X1+ X3", /* 42 */
  302. "S+C+ X1+ X3", /* 43 */
  303. " A+X1+ X3", /* 44 */
  304. "S+ A+X1+ X3", /* 45 */
  305. " C+A+X1+ X3", /* 46 */
  306. "S+C+A+X1+ X3", /* 47 */
  307. " X2+X3", /* 48 */
  308. "S+ X2+X3", /* 49 */
  309. " C+ X2+X3", /* 50 */
  310. "S+C+ X2+X3", /* 51 */
  311. " A+ X2+X3", /* 52 */
  312. "S+ A+ X2+X3", /* 53 */
  313. " C+A+ X2+X3", /* 54 */
  314. "S+C+A+ X2+X3", /* 55 */
  315. " X1+X2+X3", /* 56 */
  316. "S+ X1+X2+X3", /* 57 */
  317. " C+ X1+X2+X3", /* 58 */
  318. "S+C+ X1+X2+X3", /* 59 */
  319. " A+X1+X2+X3", /* 60 */
  320. "S+ A+X1+X2+X3", /* 61 */
  321. " C+A+X1+X2+X3", /* 62 */
  322. "S+C+A+X1+X2+X3", /* 63 */
  323. "unexpected", /* 64 */
  324. "unexpected", /* 65 */
  325. };
  326. /*************************************************************\
  327. * forward declarations *
  328. \*************************************************************/
  329. BOOL NextLine(char *Buf, DWORD cchBuf, FILE *fIn);
  330. int SkipLines(void);
  331. int isKeyWord(char *s);
  332. int getVKNum(char *pVK);
  333. char *getVKName(int VK, BOOL prefixVK_);
  334. int doKBD();
  335. int doMODIFIERS();
  336. int doSHIFTSTATE(int *nState, int aiState[]);
  337. int doATTRIBUTES(char *szAttrs);
  338. int doLAYOUT(KEYLAYOUT Layout[], int aiState[], int nState);
  339. int doDEADKEY(PDEADKEY *ppDeadKey);
  340. int doLIGATURE(PLIGATURE *ppLigature);
  341. int doKEYNAME(PKEYNAME *ppKeyName);
  342. int kbd_h(KEYLAYOUT Layout[]);
  343. int kbd_rc(void);
  344. int kbd_def(void);
  345. char *WChName(int WC, int Zero);
  346. VOID __cdecl Error(const char *Text, ... );
  347. ULONG __cdecl Warning(int nLine, const char *Text, ... );
  348. VOID DumpLayoutEntry(PKEYLAYOUT pLayout);
  349. BOOL MergeState(KEYLAYOUT[], int Vk, WCHAR, WCHAR, WCHAR, int aiState[], int nState);
  350. int kbd_c(int nState,
  351. int aiState[],
  352. char * szAttrs,
  353. KEYLAYOUT Layout[],
  354. PDEADKEY pDeadKey,
  355. PLIGATURE pLigature,
  356. PKEYNAME pKeyName,
  357. PKEYNAME pKeyNameExt,
  358. PKEYNAME pKeyNameDead);
  359. void PrintNameTable(FILE *pOut, PKEYNAME pKN, BOOL bDead);
  360. /*************************************************************\
  361. * Global variables
  362. \*************************************************************/
  363. BOOL verbose = FALSE;
  364. BOOL fallback_driver = FALSE;
  365. BOOL sanity_check = FALSE;
  366. FILE *gfpInput;
  367. char gBuf[LINEBUFSIZE];
  368. int gLineCount;
  369. LPSTR gpszFileName;
  370. char gVKeyName[WORDBUFSIZE];
  371. char gKBDName[MAXKBDNAME];
  372. char gDescription[LINEBUFSIZE];
  373. int gID = 0;
  374. char gCharName[WORDBUFSIZE];
  375. struct tm *Now;
  376. time_t Clock;
  377. void usage()
  378. {
  379. fprintf(stderr, "Usage: KbdTool [-v] [-k] file\n");
  380. fprintf(stderr, "\t[-?] display this message\n");
  381. fprintf(stderr, "\t[-v] verbose diagnostics/warnings\n");
  382. fprintf(stderr, "\t[-k] builds kbd layout for embedding in the kernel\n");
  383. fprintf(stderr, "\t[-W] performs sanity check\n");
  384. exit(EXIT_FAILURE);
  385. }
  386. /*************************************************************\
  387. * Main
  388. \*************************************************************/
  389. int _cdecl main(int argc, char** argv)
  390. {
  391. int c;
  392. int i;
  393. int nKW[NUMKEYWORD]; /* keep track of KeyWord read to prevent duplicates */
  394. int iKW;
  395. int nState; /* number of states */
  396. int aiState[MAXSTATES];
  397. char szAttrs[128] = "\0";
  398. int nTotal = 0;
  399. int nFailH = 0;
  400. int nFailC = 0;
  401. int nFailRC = 0;
  402. int nFailDEF = 0;
  403. KEYLAYOUT Layout[NUMSCVK];
  404. PDEADKEY pDeadKey = NULL;
  405. PLIGATURE pLigature = NULL;
  406. PKEYNAME pKeyName = NULL;
  407. PKEYNAME pKeyNameExt = NULL;
  408. PKEYNAME pKeyNameDead = NULL;
  409. printf("\nKbdTool v%d.%02d - convert keyboard text file to C file\n\n",
  410. gVersion, gSubVersion);
  411. while ((c = getopt(argc, argv, "vkW?")) != EOF) {
  412. switch (c) {
  413. case 'v':
  414. verbose = TRUE;
  415. break;
  416. case 'k': // means 'kernel'
  417. fallback_driver = TRUE;
  418. break;
  419. case 'W': // Turn on warning
  420. sanity_check = TRUE;
  421. break;
  422. case '?':
  423. default:
  424. usage();
  425. // never reaches here
  426. }
  427. }
  428. if (optind == argc) {
  429. usage();
  430. // never reaches here
  431. }
  432. argv = argv + optind;
  433. while (*argv) {
  434. nTotal++;
  435. gpszFileName = *argv;
  436. if ((gfpInput = fopen(*argv, "rt")) == NULL) {
  437. Error("can't open for read\n");
  438. nFailH++;
  439. nFailC++;
  440. nFailRC++;
  441. nFailDEF++;
  442. argv++;
  443. continue;
  444. }
  445. printf("%-23s:\n", *argv);
  446. /* initialize for each input file */
  447. for (i = 0; i < NUMKEYWORD; i++) {
  448. nKW[i]=0;
  449. }
  450. gLineCount = 0;
  451. /**********************************/
  452. if ((iKW = SkipLines()) >= NUMKEYWORD) {
  453. fclose(gfpInput);
  454. Error("no keyword found\n");
  455. nFailH++;
  456. nFailC++;
  457. nFailRC++;
  458. nFailDEF++;
  459. continue;
  460. }
  461. while (iKW < NUMKEYWORD - 1) {
  462. nKW[iKW]++;
  463. if (iKW != DEADKEYCODE && nKW[iKW] > 1 && verbose) {
  464. Warning(0, "duplicate %s", KeyWord[iKW]);
  465. }
  466. switch (iKW) {
  467. case KEYWORD_KBD:
  468. iKW = doKBD();
  469. break;
  470. case KEYWORD_VERSION: // ignored for now
  471. iKW = SkipLines();
  472. break;
  473. case KEYWORD_MODIFIERS:
  474. iKW = doMODIFIERS();
  475. break;
  476. case KEYWORD_SHIFTSTATE:
  477. iKW = doSHIFTSTATE(&nState, aiState);
  478. if (nState < 2) {
  479. fclose(gfpInput);
  480. Error("must have at least 2 states\n");
  481. nFailH++;
  482. nFailC++;
  483. continue;
  484. }
  485. break;
  486. case KEYWORD_ATTRIBUTES:
  487. iKW = doATTRIBUTES(szAttrs);
  488. break;
  489. case KEYWORD_LAYOUT:
  490. if ((iKW = doLAYOUT(Layout, aiState, nState)) == -1) {
  491. fclose(gfpInput);
  492. return EXIT_FAILURE;
  493. }
  494. /* add layout checking later */
  495. break;
  496. case KEYWORD_DEADKEY:
  497. if ((iKW = doDEADKEY(&pDeadKey)) == -1) {
  498. fclose(gfpInput);
  499. return EXIT_FAILURE;
  500. }
  501. break;
  502. case KEYWORD_LIGATURE:
  503. if ((iKW = doLIGATURE(&pLigature)) == -1) {
  504. fclose(gfpInput);
  505. return EXIT_FAILURE;
  506. }
  507. break;
  508. case KEYWORD_KEYNAME:
  509. if ((iKW = doKEYNAME(&pKeyName)) == -1) {
  510. fclose(gfpInput);
  511. return EXIT_FAILURE;
  512. }
  513. break;
  514. case KEYWORD_KEYNAME_EXT:
  515. if ((iKW = doKEYNAME(&pKeyNameExt)) == -1) {
  516. fclose(gfpInput);
  517. return EXIT_FAILURE;
  518. }
  519. break;
  520. case KEYWORD_KEYNAME_DEAD:
  521. if ((iKW = doKEYNAME(&pKeyNameDead)) == -1) {
  522. fclose(gfpInput);
  523. return EXIT_FAILURE;
  524. }
  525. break;
  526. default:
  527. break;
  528. }
  529. }
  530. fclose(gfpInput);
  531. /* add later : checking for LAYOUT & DEADKEY */
  532. time(&Clock);
  533. Now = localtime(&Clock);
  534. if (!fallback_driver && kbd_h(Layout) == FAILURE) {
  535. nFailH++;
  536. }
  537. if (!fallback_driver && kbd_rc() != SUCCESS) {
  538. nFailRC++;
  539. }
  540. if (kbd_c(nState, aiState, szAttrs, Layout,
  541. pDeadKey, pLigature, pKeyName, pKeyNameExt, pKeyNameDead) == FAILURE) {
  542. nFailC++;
  543. }
  544. if (!fallback_driver && kbd_def() != SUCCESS) {
  545. nFailDEF++;
  546. }
  547. printf("\n");
  548. argv++;
  549. }
  550. printf("\n %13d ->% 12d %12d %12d %12d\n",
  551. nTotal, nTotal - nFailH, nTotal - nFailRC,
  552. nTotal - nFailC, nTotal - nFailDEF);
  553. return EXIT_SUCCESS;
  554. }
  555. /*************************************************************\
  556. * Check keyword
  557. * Return: 0 - 8 for valid keyword
  558. * 9 for invalid keyword
  559. \*************************************************************/
  560. int isKeyWord(char *s)
  561. {
  562. int i;
  563. for(i = 0; i < NUMKEYWORD; i++)
  564. {
  565. if(_strcmpi(KeyWord[i], s) == 0)
  566. {
  567. return i;
  568. }
  569. }
  570. return NOT_KEYWORD;
  571. }
  572. /*************************************************************\
  573. * Skip lines till a valid keyword is available
  574. * Return: 0 - 8 for valid keyword
  575. * 9 for invalid keyword
  576. \*************************************************************/
  577. int SkipLines()
  578. {
  579. int iKW;
  580. char KW[WORDBUFSIZE];
  581. while (NextLine(gBuf, LINEBUFSIZE, gfpInput))
  582. {
  583. if(sscanf(gBuf, "%s", KW) == 1)
  584. {
  585. if((iKW = isKeyWord(KW)) < NUMKEYWORD)
  586. {
  587. return iKW;
  588. }
  589. }
  590. }
  591. return NUMKEYWORD;
  592. }
  593. /*************************************************************\
  594. * Convert Virtual Key name to integer
  595. * Return : -1 if fail
  596. \*************************************************************/
  597. int getVKNum(char *pVK)
  598. {
  599. int i, len;
  600. len = strlen(pVK);
  601. if (len < 1) {
  602. return -1;
  603. }
  604. if (len == 1) {
  605. if (*pVK >= '0' && *pVK <= '9') {
  606. return *pVK;
  607. }
  608. *pVK = (char)toupper(*pVK);
  609. if (*pVK >= 'A' && *pVK <='Z') {
  610. return *pVK;
  611. }
  612. } else {
  613. for (i = 0; i < NUMVKNAME; i++) {
  614. if(_strcmpi(VKName[i].pName, pVK) == 0) {
  615. return VKName[i].VKey;
  616. }
  617. }
  618. /*
  619. * Hey! It's unknown! Perhaps it is a new one, in which
  620. * case it must be of the form 0xNN
  621. */
  622. if (pVK[0] == '0' &&
  623. (pVK[1] == 'x' || pVK[1] == 'X')) {
  624. pVK[1] = 'x';
  625. if (sscanf(pVK, "0x%x", &i) == 1) {
  626. return i;
  627. }
  628. }
  629. }
  630. return -1;
  631. }
  632. /*************************************************************\
  633. * Convert VK integer to name and store it in gVKeyName
  634. \*************************************************************/
  635. char *getVKName(int VK, BOOL prefixVK_)
  636. {
  637. int i;
  638. char *s;
  639. s = gVKeyName;
  640. if((VK >= 'A' && VK <= 'Z') || (VK >= '0' && VK <= '9'))
  641. {
  642. *s++ = '\'';
  643. *s++ = (char)VK;
  644. *s++ = '\'';
  645. *s = '\0';
  646. return gVKeyName;
  647. }
  648. if(prefixVK_)
  649. {
  650. strcpy(gVKeyName, "VK_");
  651. }
  652. else
  653. {
  654. strcpy(gVKeyName, "");
  655. }
  656. for(i = 0; i < NUMVKNAME; i++)
  657. {
  658. if(VKName[i].VKey == VK)
  659. {
  660. strcat(s, VKName[i].pName);
  661. return gVKeyName;
  662. }
  663. }
  664. strcpy(gVKeyName, "#ERROR#");
  665. return gVKeyName;
  666. }
  667. /*************************************************************\
  668. * KBD section
  669. * read in gKBDName and gDescription if any
  670. * Return : next keyword
  671. \*************************************************************/
  672. int doKBD()
  673. {
  674. char *p;
  675. *gKBDName = '\0';
  676. *gDescription = '\0';
  677. if (sscanf(gBuf, "KBD %5s \"%40[^\"]\" %d", gKBDName, gDescription, &gID) < 2)
  678. {
  679. // if (sscanf(gBuf, "KBD %5s ;%40[^\n]", gKBDName, gDescription) < 2)
  680. // {
  681. Error("unrecognized keyword");
  682. // }
  683. }
  684. return (SkipLines());
  685. }
  686. /****************************************************************************\
  687. * MODIFIERS section [OPTIONAL]
  688. * Additions to the standard MODIFIERS CharModifiers section.
  689. * Useful now for adding RCONTROL shiftstates (eg: CAN/CSA prototype)
  690. * Useful in future for KBDGRPSELTAP keys that flip the kbd into an alternate
  691. * layout until the next character is produced (then reverts to main layout).
  692. *
  693. * Example of syntax is
  694. * MODIFIERS
  695. * RCONTROL 8
  696. * RSHIFT KBDGRPSELTAP
  697. * I hope to be able to extend this to allow key combos as KBDGRPSELTAP, since
  698. * the CAN/CSA keyboard may want to have RShift+AltGr flip into the alternate
  699. * layout (group 2 character set) in addition to just RCtrl, since some terminal
  700. * emulators use the RCtrl key as an "Enter" key.
  701. \****************************************************************************/
  702. int doMODIFIERS()
  703. {
  704. int i = 3;
  705. int iKW = NOT_KEYWORD;
  706. char achModifier[WORDBUFSIZE];
  707. char achModBits[LINEBUFSIZE];
  708. while(NextLine(gBuf, LINEBUFSIZE, gfpInput)) {
  709. if (sscanf(gBuf, "%s", achModifier) != 1) {
  710. continue;
  711. }
  712. if ((iKW = isKeyWord(achModifier)) < NUMKEYWORD) {
  713. break;
  714. }
  715. if (sscanf(gBuf, " %s %[^;\n]", achModifier, achModBits) < 2) {
  716. Warning(0, "poorly formed MODIFIER entry");
  717. break;
  718. }
  719. Modifiers[i].Vk = getVKNum(achModifier);
  720. Modifiers[i].pszModBits = _strdup(achModBits); // never freed!
  721. if (++i > (sizeof(Modifiers)/sizeof(Modifiers[0]))) {
  722. Warning(0, "Too many MODIFIER entries");
  723. break;
  724. }
  725. }
  726. return iKW;
  727. }
  728. /*************************************************************\
  729. * SHIFTSTATE section
  730. * read number of states and each state
  731. * return : next keyword
  732. \*************************************************************/
  733. int doSHIFTSTATE(int *nState, int* aiState)
  734. {
  735. int i;
  736. int iKW;
  737. int iSt;
  738. char Tmp[WORDBUFSIZE];
  739. for(i = 0; i < MAXSTATES; i++)
  740. {
  741. aiState[i] = -1;
  742. }
  743. *nState = 0;
  744. while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
  745. {
  746. if(sscanf(gBuf, "%s", Tmp) != 1)
  747. {
  748. continue;
  749. }
  750. if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
  751. {
  752. break;
  753. }
  754. if(sscanf(gBuf, " %2s[012367]", Tmp) != 1)
  755. {
  756. if (verbose) {
  757. Warning(0, "invalid state");
  758. }
  759. continue; /* add printf error later */
  760. }
  761. iSt = atoi(Tmp);
  762. for (i = 0; i < *nState; i++) {
  763. if (aiState[i] == iSt && verbose) {
  764. Warning(0, "duplicate state %d", iSt);
  765. break;
  766. }
  767. }
  768. if (*nState < MAXSTATES) {
  769. aiState[(*nState)++] = iSt;
  770. } else {
  771. if (verbose) {
  772. Warning(0, "too many states %d", *nState);
  773. }
  774. }
  775. }
  776. return iKW;
  777. }
  778. /****************************************************************************\
  779. * ATTRIBUTES section [OPTIONAL]
  780. *
  781. * Example of syntax is
  782. * ATTRIBUTES
  783. * LRM_RLM
  784. * SHIFTLOCK
  785. * ALTGR
  786. *
  787. * These convert to
  788. * KLLF_LRM_RLM (layout generates LRM/RLM 200E/200F with L/RShift+BackSpace)
  789. * KLLF_SHIFTLOCK (Capslock only turns CapsLock on, Shift turns it off)
  790. * KLLF_ALTGR (this is normally inferred by number of states > 5)
  791. *
  792. \****************************************************************************/
  793. char *Attribute[] = {
  794. "LRM_RLM" ,
  795. "SHIFTLOCK",
  796. "ALTGR"
  797. };
  798. #define NUMATTR (sizeof(Attribute) / sizeof(Attribute[0]))
  799. /*
  800. * Returns next key word encountered, and places in szAttr:
  801. * empty string ("") or
  802. * something like "KLLF_SHIFTLOCK" or "KLLF_SHIFTLOCK | KLLF_LRM_RLM"
  803. */
  804. int doATTRIBUTES(char *szAttrs)
  805. {
  806. int iKW = NOT_KEYWORD;
  807. int i;
  808. char achAttribute[WORDBUFSIZE];
  809. szAttrs[0] = '\0';
  810. while (NextLine(gBuf, LINEBUFSIZE, gfpInput)) {
  811. if (sscanf(gBuf, "%s", achAttribute) != 1) {
  812. continue;
  813. }
  814. if ((iKW = isKeyWord(achAttribute)) < NUMKEYWORD) {
  815. break;
  816. }
  817. for (i = 0; i < NUMATTR; i++) {
  818. if (_strcmpi(Attribute[i], achAttribute) == 0) {
  819. if (szAttrs[0] != '\0') {
  820. strcat(szAttrs, " | ");
  821. }
  822. strcat(szAttrs, "KLLF_");
  823. strcat(szAttrs, Attribute[i]);
  824. }
  825. }
  826. if (szAttrs[0] == '\0') {
  827. Warning(0, "poorly formed ATTRIBUTES entry");
  828. break;
  829. }
  830. }
  831. return iKW;
  832. }
  833. /**********************************************************************\
  834. * GetCharacter
  835. * Scans the string in p to return a character value and type
  836. * syntax in p is:
  837. * xxxx four hex digits, may be followed by a @ or %
  838. * eg: 00e8, 00AF@, aaaa%
  839. * c a character, may be followed with @ or %
  840. * eg: x, ^@, %%
  841. * -1 not a character
  842. *
  843. * return : character value (0xFFFF if badly formed)
  844. * type of character in pdwType
  845. * 0 plain char (ends with neither @ nor %)
  846. * CHARTYPE_DEAD dead char (ends with @)
  847. * CHARTYPE_LIG ligature (ends with %)
  848. * CHARTYPE_BAD badly formed character value, exit.
  849. *
  850. \**********************************************************************/
  851. #define CHARTYPE_DEAD 1
  852. #define CHARTYPE_LIG 2
  853. #define CHARTYPE_BAD 3
  854. WCHAR GetCharacter(unsigned char *p, DWORD *pdwType)
  855. {
  856. int Len;
  857. DWORD dwCh;
  858. *pdwType = 0;
  859. // if the last char is @ or % it is dead or ligature
  860. if (Len = strlen(p) - 1) {
  861. if (*(p + Len) == '@') {
  862. *pdwType = CHARTYPE_DEAD;
  863. } else if (*(p + Len) == '%') {
  864. *pdwType = CHARTYPE_LIG;
  865. }
  866. }
  867. if (Len < 2) {
  868. return *p;
  869. } else if (sscanf(p, "%4x", &dwCh) != 1) {
  870. if (verbose) {
  871. Warning(0, "LAYOUT error %s", p);
  872. }
  873. *pdwType = CHARTYPE_BAD;
  874. return 0;
  875. } else {
  876. return (WCHAR)dwCh;
  877. }
  878. }
  879. int WToUpper(int wch)
  880. {
  881. WCHAR src[1] = { (WCHAR)wch };
  882. WCHAR result[1];
  883. if (LCMapStringW(0, LCMAP_UPPERCASE, src, 1, result, 1) == 0) {
  884. return L'\0';
  885. }
  886. return result[0];
  887. }
  888. /*************************************************************\
  889. * LAYOUT section
  890. * return : next keyword
  891. * -1 if memory problem
  892. \*************************************************************/
  893. int doLAYOUT(KEYLAYOUT Layout[], int aiState[], int nState)
  894. {
  895. int i, idx, iCtrlState;
  896. BOOL fHasCharacters;
  897. int iKW;
  898. int Len;
  899. USHORT Scan;
  900. DWORD WChr;
  901. char Cap[MAXWCLENGTH];
  902. unsigned char WC[MAXSTATES][MAXWCLENGTH];
  903. char Tmp[WORDBUFSIZE];
  904. int i1, i2;
  905. int iScVk;
  906. memset(Layout, 0, NUMSCVK * sizeof(KEYLAYOUT));
  907. // Initialize layout entries
  908. for (idx = 0; idx < NUMSCVK; idx++) {
  909. Layout[idx].defined = FALSE;
  910. Layout[idx].nState = 0;
  911. }
  912. /*
  913. * Accumulate layout entries in the order they are read
  914. */
  915. idx = -1;
  916. while (NextLine(gBuf, LINEBUFSIZE, gfpInput)) {
  917. if (sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';') {
  918. continue;
  919. }
  920. if ((iKW = isKeyWord(Tmp)) < NUMKEYWORD) {
  921. break;
  922. }
  923. i = sscanf(gBuf, " %x %s %s", &Scan, Tmp, Cap);
  924. if (i == 3) {
  925. fHasCharacters = TRUE;
  926. } else if (i == 2) {
  927. fHasCharacters = FALSE;
  928. } else {
  929. Error("not enough entries on line");
  930. return -1;
  931. }
  932. /*
  933. * We have found an Entry
  934. */
  935. idx++;
  936. if (idx >= NUMSCVK) {
  937. Error("ScanCode %02x - too many scancodes", Scan);
  938. return -1;
  939. }
  940. Layout[idx].Scan = Scan;
  941. Layout[idx].nLine = gLineCount;
  942. /*
  943. * Find and use the Default values for this Scan
  944. */
  945. for (iScVk = 0; iScVk < NUMSCVK; iScVk++) {
  946. if (ScVk[iScVk].Scan == 0xffff) {
  947. // We didn't find a match (the 0xffff entries come last)
  948. Warning(0, "defining new scancode 0x%2X, %s", Scan, Tmp);
  949. Layout[idx].VKey = (unsigned char)getVKNum(Tmp);
  950. Layout[idx].defined = TRUE;
  951. ScVk[iScVk].bUsed = TRUE;
  952. break;
  953. }
  954. if (Scan == ScVk[iScVk].Scan) {
  955. if (ScVk[iScVk].bUsed == TRUE) {
  956. Error("Scancode %X was previously defined", Scan);
  957. return -1;
  958. }
  959. if (ScVk[iScVk].VKey == 0xff) {
  960. Error("Scancode %X is reserved", Scan);
  961. return -1;
  962. }
  963. // Save the default VK for generating kbd*.h
  964. Layout[idx].VKeyDefault = ScVk[iScVk].VKey;
  965. Layout[idx].VKeyName = ScVk[iScVk].VKeyName;
  966. Layout[idx].defined = TRUE;
  967. ScVk[iScVk].bUsed = TRUE;
  968. break;
  969. }
  970. }
  971. iScVk = 0xFFFF; // finished with iScVk for now
  972. if ((Layout[idx].VKey = (unsigned char)getVKNum(Tmp)) == -1) {
  973. if (verbose) {
  974. Warning(0, "invalid VK %s", Tmp);
  975. }
  976. continue;
  977. }
  978. if (fHasCharacters) {
  979. if(_strcmpi(Cap, "SGCAP") == 0) {
  980. *Cap = '2';
  981. }
  982. if(sscanf(Cap, "%1d[012]", &(Layout[idx].Cap)) != 1) {
  983. Error("invalid Cap %s", Cap);
  984. return -1;
  985. }
  986. }
  987. if ((Layout[idx].nState = sscanf(gBuf,
  988. " %*s %*s %*s %s %s %s %s %s %s %s %s",
  989. WC[0], WC[1], WC[2], WC[3], WC[4], WC[5], WC[6], WC[7])) < 2)
  990. {
  991. if (fHasCharacters) {
  992. Error("must have at least 2 characters");
  993. return -1;
  994. }
  995. }
  996. for (i = 0; i < Layout[idx].nState; i++) {
  997. DWORD dwCharType;
  998. if (_strcmpi(WC[i], "-1") == 0) {
  999. Layout[idx].WCh[i] = -1;
  1000. continue;
  1001. }
  1002. Layout[idx].WCh[i] = GetCharacter(WC[i], &dwCharType);
  1003. if (dwCharType == CHARTYPE_DEAD) {
  1004. Layout[idx].DKy[i] = 1;
  1005. } else if (dwCharType == CHARTYPE_LIG) {
  1006. Layout[idx].LKy[i] = 1;
  1007. } else if (dwCharType == CHARTYPE_BAD) {
  1008. break;
  1009. }
  1010. }
  1011. if (sanity_check && Layout[idx].nState > 0) {
  1012. int nAltGr, nShiftAltGr;
  1013. /*
  1014. * Check that characters a-z and A-Z are on VK_A - VK_Z
  1015. * N.b. maybe overactive warnings for the intl layouts.
  1016. */
  1017. if (((Layout[idx].WCh[0] >= 'a') && (Layout[idx].WCh[0] <= 'z')) ||
  1018. ((Layout[idx].WCh[1] >= 'A') && (Layout[idx].WCh[1] <= 'Z'))) {
  1019. if ((Layout[idx].VKey != _toupper(Layout[idx].WCh[0])) && (Layout[idx].VKey != Layout[idx].WCh[1])) {
  1020. Warning(0, "VK_%s (0x%2x) does not match %c %c",
  1021. Tmp, Layout[idx].VKey, Layout[idx].WCh[0], Layout[idx].WCh[1]);
  1022. }
  1023. }
  1024. /*
  1025. * Check that CAPLOKALTGR is set appropriately
  1026. */
  1027. nAltGr = 0;
  1028. nShiftAltGr = 0;
  1029. for (i = 0; i < nState; i++) {
  1030. if (aiState[i] == (KBDCTRL | KBDALT)) {
  1031. nAltGr = i;
  1032. } else if (aiState[i] == (KBDCTRL | KBDALT | KBDSHIFT)) {
  1033. nShiftAltGr = i;
  1034. }
  1035. }
  1036. /*
  1037. * Check only if nShiftAltGr has a valid character; i.e. not zero, nor a dead key.
  1038. */
  1039. if (nAltGr && nShiftAltGr && Layout[idx].WCh[nShiftAltGr] && Layout[idx].WCh[nShiftAltGr] != -1) {
  1040. if (Layout[idx].WCh[nShiftAltGr] != WToUpper(Layout[idx].WCh[nAltGr])) {
  1041. if (Layout[idx].Cap & CAPLOKALTGR) {
  1042. Warning(0, "VK_%s (0x%2x) [Shift]AltGr = [%2x],%2x should not be CAPLOKALTGR?",
  1043. Tmp, Layout[idx].VKey,
  1044. Layout[idx].WCh[nAltGr], Layout[idx].WCh[nShiftAltGr]);
  1045. }
  1046. } else if (Layout[idx].WCh[nShiftAltGr] != Layout[idx].WCh[nAltGr]) {
  1047. /*
  1048. * If the character is completely same, no need for CAPLOKALTGR.
  1049. */
  1050. if ((Layout[idx].Cap & CAPLOKALTGR) == 0) {
  1051. Warning(0, "VK_%s (0x%2x) [Shift]AltGr = [%2x],%2x should be CAPLOKALTGR?",
  1052. Tmp, Layout[idx].VKey,
  1053. Layout[idx].WCh[nAltGr], Layout[idx].WCh[nShiftAltGr]);
  1054. }
  1055. }
  1056. }
  1057. }
  1058. /* SGCAP: read the next line */
  1059. if (Layout[idx].Cap & 0x02) {
  1060. if((Layout[idx].pSGCAP = malloc( sizeof(KEYLAYOUT) )) == NULL)
  1061. {
  1062. Error("can't allocate SGCAP struct");
  1063. return -1;
  1064. }
  1065. memset(Layout[idx].pSGCAP, 0, sizeof(KEYLAYOUT));
  1066. if (NextLine(gBuf, LINEBUFSIZE, gfpInput) &&
  1067. (Layout[idx].pSGCAP->nState = sscanf(gBuf, " -1 -1 0 %s %s %s %s %s %s %s %s",
  1068. WC[0], WC[1], WC[2], WC[3], WC[4], WC[5], WC[6], WC[7])) != 0) {
  1069. // DumpLayoutEntry(&Layout[idx]);
  1070. for (i = 0; i < Layout[idx].pSGCAP->nState; i++) {
  1071. if (_strcmpi(WC[i], "-1") == 0) {
  1072. Layout[idx].pSGCAP->WCh[i] = -1;
  1073. continue;
  1074. }
  1075. if ((Len = strlen(WC[i]) - 1) > 0 && *WC[i + Len] == '@') {
  1076. Layout[idx].pSGCAP->DKy[i] = 1; /* it is a dead key */
  1077. }
  1078. if (Len == 0) {
  1079. Layout[idx].pSGCAP->WCh[i] = *WC[i];
  1080. } else {
  1081. if (sscanf(WC[i], "%4x", &WChr) != 1) {
  1082. if (verbose) {
  1083. Warning(0, "SGCAP LAYOUT error %s", WC[i]);
  1084. }
  1085. continue;
  1086. } else {
  1087. Layout[idx].pSGCAP->WCh[i] = WChr;
  1088. }
  1089. }
  1090. }
  1091. } else {
  1092. Error("invalid SGCAP");
  1093. }
  1094. }
  1095. // DumpLayoutEntry(&Layout[idx]);
  1096. }
  1097. /*
  1098. * Pick up any unused ScVk[] entries (defaults)
  1099. */
  1100. for (iScVk = 0; iScVk < NUMSCVK; iScVk++) {
  1101. // if we reach 0xffff, we have come to the end.
  1102. if (ScVk[iScVk].Scan == 0xffff) {
  1103. break;
  1104. }
  1105. if (!ScVk[iScVk].bUsed) {
  1106. idx++;
  1107. if (idx >= NUMSCVK) {
  1108. Error("ScanCode %02x - too many scancodes", ScVk[iScVk].Scan);
  1109. return -1;
  1110. }
  1111. Layout[idx].Scan = ScVk[iScVk].Scan;
  1112. Layout[idx].VKey = ScVk[iScVk].VKey;
  1113. Layout[idx].VKeyDefault = ScVk[iScVk].VKey;
  1114. Layout[idx].VKeyName = ScVk[iScVk].VKeyName;
  1115. Layout[idx].defined = TRUE;
  1116. Layout[idx].nLine = 0;
  1117. // DumpLayoutEntry(&Layout[idx]);
  1118. } else {
  1119. ScVk[iScVk].bUsed = FALSE;
  1120. }
  1121. }
  1122. /*
  1123. * Now make sure some standard Ctrl characters are present
  1124. */
  1125. MergeState(Layout, VK_BACK, L'\b', L'\b', 0x007f, aiState, nState);
  1126. MergeState(Layout, VK_CANCEL, 0x0003, 0x0003, 0x0003, aiState, nState);
  1127. MergeState(Layout, VK_ESCAPE, 0x001b, 0x001b, 0x001b, aiState, nState);
  1128. MergeState(Layout, VK_RETURN, L'\r', L'\r', L'\n', aiState, nState);
  1129. MergeState(Layout, VK_SPACE, L' ', L' ', L' ', aiState, nState);
  1130. /*
  1131. * Check VK not duplicated
  1132. */
  1133. for (idx = 0; idx < NUMSCVK; idx++) {
  1134. for (i = idx + 1; i < NUMSCVK; i++) {
  1135. if (Layout[idx].VKey == Layout[i].VKey) {
  1136. if (Layout[idx].VKey == 0xFF) {
  1137. // undefined extended and non-extended versions of the same key
  1138. continue;
  1139. }
  1140. if ((BYTE)Layout[idx].Scan == (BYTE)Layout[i].Scan) {
  1141. // extended and non-extended versions of the same key
  1142. continue;
  1143. }
  1144. Error("VK_%s (%02x) found at scancode %02x and %02x",
  1145. getVKName(Layout[idx].VKey, 0), Layout[idx].VKey, Layout[idx].Scan, Layout[i].Scan);
  1146. }
  1147. }
  1148. }
  1149. /*
  1150. * Find duplicated characters and warn of VkKeyScanEx results
  1151. */
  1152. if (verbose) {
  1153. for (i1 = 0; i1 < NUMSCVK; i1++) {
  1154. for (i2 = i1 + 1; i2 < NUMSCVK; i2++) {
  1155. int ich1, ich2;
  1156. for (ich1 = 0; ich1 < Layout[i1].nState; ich1++) {
  1157. if (Layout[i1].WCh[ich1] == -1) {
  1158. // there may be many WCH_NONEs (padding, or empty holes)
  1159. continue;
  1160. }
  1161. if (Layout[i1].WCh[ich1] < 0x20) {
  1162. // Don't care about Ctrl chars.
  1163. // these are usually duplicated eg: Ctrl-M == Return, etc.
  1164. continue;
  1165. }
  1166. if ((Layout[i1].VKey == VK_DECIMAL) || (Layout[i2].VKey == VK_DECIMAL)) {
  1167. // kbdtool has put VK_DECIMAL at the end just for VkKeyScanEx
  1168. // It is usually period or comma, and we prefer to get those
  1169. // from the main section of the keyboard.
  1170. continue;
  1171. }
  1172. for (ich2 = 0; ich2 < Layout[i2].nState; ich2++) {
  1173. if (Layout[i1].WCh[ich1] == Layout[i2].WCh[ich2]) {
  1174. char achVK1[40];
  1175. char achVK2[40];
  1176. strncpy(achVK1, getVKName(Layout[i1].VKey, TRUE), sizeof(achVK1));
  1177. strncpy(achVK2, getVKName(Layout[i2].VKey, TRUE), sizeof(achVK2));
  1178. Warning(Layout[i1].nLine,
  1179. "%04x is on %s and %s",
  1180. Layout[i1].WCh[ich1],
  1181. achVK1, achVK2);
  1182. }
  1183. }
  1184. }
  1185. }
  1186. }
  1187. }
  1188. return iKW;
  1189. }
  1190. /*************************************************************\
  1191. * DEADKEY section
  1192. * return : next keyword
  1193. * -1 if memory problem
  1194. \*************************************************************/
  1195. int doDEADKEY(PDEADKEY *ppDeadKey)
  1196. {
  1197. char Tmp[WORDBUFSIZE];
  1198. int iKW;
  1199. DEADKEY *pDeadKey;
  1200. PDEADTRANS pDeadTrans;
  1201. PDEADTRANS *ppDeadTrans;
  1202. DWORD dw;
  1203. static PDEADKEY pLastDeadKey;
  1204. int iLen;
  1205. DWORD dwCharType;
  1206. if (sscanf(gBuf, " DEADKEY %s", Tmp) != 1) {
  1207. Warning(0, "missing dead key");
  1208. return SkipLines();
  1209. }
  1210. /* add later : check if dw is in Layout*/
  1211. if((pDeadKey = (DEADKEY*) malloc( sizeof(DEADKEY) )) == NULL)
  1212. {
  1213. Error("can't allocate DEADKEY struct");
  1214. return -1;
  1215. }
  1216. pDeadKey->Dead = GetCharacter(Tmp, &dwCharType);
  1217. if (dwCharType != 0) {
  1218. Error("DEADKEY character value badly formed");
  1219. return -1;
  1220. }
  1221. pDeadKey->pNext = NULL;
  1222. pDeadKey->pDeadTrans = NULL;
  1223. /*
  1224. * Link into end of list (maintaining original order)
  1225. */
  1226. if (*ppDeadKey) {
  1227. ppDeadKey = &(pLastDeadKey->pNext);
  1228. }
  1229. *ppDeadKey = pDeadKey;
  1230. pLastDeadKey = pDeadKey;
  1231. // ppDeadKey = &(pDeadKey->pNext);
  1232. ppDeadTrans = &(pDeadKey->pDeadTrans);
  1233. while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
  1234. {
  1235. if (sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';') {
  1236. continue;
  1237. }
  1238. if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
  1239. {
  1240. break;
  1241. }
  1242. // get base character
  1243. dw = GetCharacter(Tmp, &dwCharType);
  1244. if (dwCharType != 0) {
  1245. Error("DEADKEY %x: base character value badly formed", pDeadKey->Dead);
  1246. return -1;
  1247. }
  1248. /* add later : check dw */
  1249. if((pDeadTrans = (DEADTRANS *) malloc( sizeof(DEADTRANS) )) == NULL)
  1250. {
  1251. Error("can't allocate DEADTRANS struct");
  1252. return -1;
  1253. }
  1254. memset(pDeadTrans, 0, sizeof(DEADTRANS));
  1255. pDeadTrans->pNext = NULL;
  1256. pDeadTrans->Base = dw;
  1257. pDeadTrans->uFlags = 0;
  1258. /*
  1259. * Link to end of list (maintaining original order)
  1260. */
  1261. *ppDeadTrans = pDeadTrans;
  1262. ppDeadTrans = &(pDeadTrans->pNext);
  1263. if (sscanf(gBuf, " %*s %s", Tmp) != 1) {
  1264. if (verbose) {
  1265. Warning(0, "missing deadtrans key");
  1266. }
  1267. continue;
  1268. }
  1269. pDeadTrans->WChar = GetCharacter(Tmp, &dwCharType);
  1270. if (dwCharType == CHARTYPE_DEAD) {
  1271. pDeadTrans->uFlags |= 0x0001; // DKF_DEAD in oak\inc\kbd.h
  1272. } else if (dwCharType != 0) {
  1273. Error("DEADKEY character value badly formed");
  1274. return -1;
  1275. }
  1276. }
  1277. return iKW;
  1278. }
  1279. static int gMaxLigature = 0;
  1280. /*************************************************************\
  1281. * LIGATURE section
  1282. * return : next keyword
  1283. * -1 if memory problem
  1284. \*************************************************************/
  1285. int doLIGATURE(PLIGATURE *ppLigature)
  1286. {
  1287. int i;
  1288. int iKW;
  1289. DWORD WChr;
  1290. char Mod[MAXWCLENGTH];
  1291. unsigned char WC[MAXLIGATURES+1][MAXWCLENGTH];
  1292. char Tmp[WORDBUFSIZE];
  1293. LIGATURE *pLigature;
  1294. static PLIGATURE pLastLigature;
  1295. while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
  1296. {
  1297. if(sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';')
  1298. {
  1299. continue;
  1300. }
  1301. if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
  1302. {
  1303. break;
  1304. }
  1305. if(sscanf(gBuf, " %s %s", Tmp, Mod) != 2)
  1306. {
  1307. if(verbose)
  1308. {
  1309. Warning(0, "invalid LIGATURE");
  1310. }
  1311. continue;
  1312. }
  1313. if((pLigature = (LIGATURE*) malloc( sizeof(LIGATURE) )) == NULL)
  1314. {
  1315. Error("can't allocate LIGATURE struct");
  1316. return -1;
  1317. }
  1318. pLigature->pNext = NULL;
  1319. if((pLigature->VKey = (unsigned char)getVKNum(Tmp)) == -1)
  1320. {
  1321. if(verbose)
  1322. {
  1323. Warning(0, "invalid VK %s", Tmp);
  1324. }
  1325. continue;
  1326. }
  1327. if(sscanf(Mod, "%1d[012367]", &(pLigature->Mod)) != 1)
  1328. {
  1329. if(verbose)
  1330. {
  1331. Warning(0, "invalid Mod %s", Mod);
  1332. }
  1333. continue;
  1334. }
  1335. /*
  1336. * We're currently limited to MAXLIGATURES characters per
  1337. * ligature. In order to support more characters per ligature,
  1338. * increase this define (in kbdx.h).
  1339. */
  1340. if((pLigature->nCharacters = \
  1341. sscanf(gBuf, " %*s %*s %s %s %s %s %s %s", \
  1342. &WC[0], &WC[1], &WC[2], &WC[3], &WC[4], &WC[5])) < 2)
  1343. {
  1344. if(verbose)
  1345. {
  1346. Warning(0, "must have at least 2 characters");
  1347. }
  1348. continue;
  1349. }
  1350. if (pLigature->nCharacters > MAXLIGATURES)
  1351. {
  1352. if(verbose)
  1353. {
  1354. Warning(0, "exceeded maximum # of characters for ligature");
  1355. }
  1356. continue;
  1357. }
  1358. for(i = 0; i < pLigature->nCharacters; i++)
  1359. {
  1360. DWORD dwCharType;
  1361. pLigature->WCh[i] = GetCharacter(WC[i], &dwCharType);
  1362. if (dwCharType != 0) {
  1363. if(verbose) {
  1364. Warning(0, "LIGATURE error %s", WC[i]);
  1365. }
  1366. break;
  1367. }
  1368. }
  1369. /*
  1370. * Link into end of list (maintaining original order)
  1371. */
  1372. if (*ppLigature) {
  1373. ppLigature = &(pLastLigature->pNext);
  1374. }
  1375. *ppLigature = pLigature;
  1376. pLastLigature = pLigature;
  1377. gMaxLigature = max(pLigature->nCharacters, gMaxLigature);
  1378. }
  1379. return iKW;
  1380. }
  1381. /*************************************************************\
  1382. * KEYNAME, KEYNAME_EXT, KEYNAME_DEAD sections
  1383. * return : next keyword
  1384. * -1 if memory problem
  1385. \*************************************************************/
  1386. int doKEYNAME(PKEYNAME *ppKeyName)
  1387. {
  1388. KEYNAME *pKN;
  1389. int iKW;
  1390. char Tmp[WORDBUFSIZE];
  1391. int Char;
  1392. char *p;
  1393. char *q;
  1394. *ppKeyName = NULL;
  1395. while(NextLine(gBuf, LINEBUFSIZE, gfpInput))
  1396. {
  1397. if(sscanf(gBuf, " %s", Tmp) != 1 || *Tmp == ';')
  1398. {
  1399. continue;
  1400. }
  1401. if((iKW = isKeyWord(Tmp)) < NUMKEYWORD)
  1402. {
  1403. break;
  1404. }
  1405. if(sscanf(Tmp, " %4x", &Char) != 1)
  1406. {
  1407. if(verbose)
  1408. {
  1409. Warning(0, "invalid char code");
  1410. }
  1411. continue;
  1412. }
  1413. /* add later : check Scan code */
  1414. if(sscanf(gBuf, " %*4x %s[^\n]", Tmp) != 1)
  1415. {
  1416. if(verbose)
  1417. {
  1418. Warning(0, "missing name");
  1419. }
  1420. continue;
  1421. }
  1422. p = strstr(gBuf, Tmp);
  1423. if((q = strchr(p, '\n')) != NULL)
  1424. {
  1425. *q = '\0';
  1426. }
  1427. if((pKN = (void*) malloc( sizeof(KEYNAME) )) == NULL)
  1428. {
  1429. Error("can't allocate KEYNAME struct");
  1430. return -1;
  1431. }
  1432. pKN->Code = Char;
  1433. pKN->pName = _strdup(p);
  1434. pKN->pNext = NULL;
  1435. /*
  1436. * Link to end of list (maintaining original order)
  1437. */
  1438. *ppKeyName = pKN;
  1439. ppKeyName = &(pKN->pNext);
  1440. }
  1441. return iKW;
  1442. }
  1443. /*************************************************************\
  1444. * write kbd*.rc *
  1445. \*************************************************************/
  1446. int kbd_rc(void)
  1447. {
  1448. char OutName[FILENAMESIZE];
  1449. char kbdname[MAXKBDNAME];
  1450. FILE *pOut;
  1451. strcpy(OutName, "KBD");
  1452. strcat(OutName, gKBDName);
  1453. strcat(OutName, ".RC");
  1454. strcpy(kbdname, gKBDName);
  1455. _strlwr(kbdname);
  1456. printf(" %12s", OutName);
  1457. if((pOut = fopen(OutName, "wt")) == NULL)
  1458. {
  1459. printf(": can't open for write; ");
  1460. return FAILURE;
  1461. }
  1462. fprintf(pOut,
  1463. "#include <windows.h>\n"
  1464. "#include <ntverp.h>\n"
  1465. "\n"
  1466. "#define VER_FILETYPE VFT_DLL\n"
  1467. "#define VER_FILESUBTYPE VFT2_DRV_KEYBOARD\n" );
  1468. fprintf(pOut,
  1469. "#define VER_FILEDESCRIPTION_STR \"%s Keyboard Layout\"\n", gDescription);
  1470. fprintf(pOut,
  1471. "#define VER_INTERNALNAME_STR \"kbd%s (%d.%d)\"\n",
  1472. kbdname, gVersion, gSubVersion);
  1473. fprintf(pOut,
  1474. "#define VER_ORIGINALFILENAME_STR \"kbd%s.dll\"\n", kbdname);
  1475. fprintf(pOut,
  1476. "\n"
  1477. "#define VER_LANGNEUTRAL\n"
  1478. "#include \"common.ver\"\n");
  1479. fclose(pOut);
  1480. return SUCCESS;
  1481. }
  1482. /*************************************************************\
  1483. * write kbd*.def *
  1484. \*************************************************************/
  1485. int kbd_def(void)
  1486. {
  1487. char OutName[FILENAMESIZE];
  1488. FILE *pOut;
  1489. strcpy(OutName, "KBD");
  1490. strcat(OutName, gKBDName);
  1491. strcat(OutName, ".DEF");
  1492. printf(" %12s", OutName);
  1493. if((pOut = fopen(OutName, "wt")) == NULL)
  1494. {
  1495. printf(": can't open for write; ");
  1496. return FAILURE;
  1497. }
  1498. fprintf(pOut,
  1499. "LIBRARY KBD%s\n"
  1500. "\n"
  1501. "EXPORTS\n"
  1502. " KbdLayerDescriptor @1\n", gKBDName);
  1503. fclose(pOut);
  1504. return SUCCESS;
  1505. }
  1506. /*************************************************************\
  1507. * write kbd*.h *
  1508. \*************************************************************/
  1509. int kbd_h(KEYLAYOUT Layout[])
  1510. {
  1511. char OutName[FILENAMESIZE];
  1512. FILE *pOut;
  1513. int nDiff = 0;
  1514. int idx;
  1515. strcpy(OutName, "KBD");
  1516. strcat(OutName, gKBDName);
  1517. strcat(OutName, ".H");
  1518. printf(" %12s ", OutName);
  1519. if((pOut = fopen(OutName, "wt")) == NULL)
  1520. {
  1521. printf(": can't open for write; ");
  1522. return FAILURE;
  1523. }
  1524. fprintf(pOut,"/****************************** Module Header ******************************\\\n"
  1525. "* Module Name: %s\n*\n* keyboard layout header for %s\n"
  1526. "*\n"
  1527. "* Copyright (c) 1985-2001, Microsoft Corporation\n"
  1528. "*\n"
  1529. "* Various defines for use by keyboard input code.\n*\n* History:\n"
  1530. "*\n"
  1531. "* created by KBDTOOL v%d.%02d %s*\n"
  1532. "\\***************************************************************************/\n\n"
  1533. , OutName, gDescription, gVersion, gSubVersion, asctime(Now));
  1534. fprintf(pOut,"/*\n"
  1535. " * kbd type should be controlled by cl command-line argument\n"
  1536. " */\n"
  1537. "#define KBD_TYPE 4\n\n"
  1538. "/*\n"
  1539. "* Include the basis of all keyboard table values\n"
  1540. "*/\n"
  1541. "#include \"kbd.h\"\n"
  1542. // "#include \"strid.h\"\n" --- do this in v3.07
  1543. );
  1544. fprintf(pOut,"/***************************************************************************\\\n"
  1545. "* The table below defines the virtual keys for various keyboard types where\n"
  1546. "* the keyboard differ from the US keyboard.\n"
  1547. "*\n"
  1548. "* _EQ() : all keyboard types have the same virtual key for this scancode\n"
  1549. "* _NE() : different virtual keys for this scancode, depending on kbd type\n"
  1550. "*\n"
  1551. "* +------+ +----------+----------+----------+----------+----------+----------+\n"
  1552. "* | Scan | | kbd | kbd | kbd | kbd | kbd | kbd |\n"
  1553. "* | code | | type 1 | type 2 | type 3 | type 4 | type 5 | type 6 |\n"
  1554. "\\****+-------+_+----------+----------+----------+----------+----------+----------+*/\n\n");
  1555. for (idx = 0; idx < NUMSCVK; idx++) {
  1556. if (Layout[idx].defined && (Layout[idx].VKey != Layout[idx].VKeyDefault))
  1557. {
  1558. char ch;
  1559. switch (Layout[idx].Scan & 0xFF00) {
  1560. case 0xE100:
  1561. ch = 'Y';
  1562. break;
  1563. case 0xE000:
  1564. ch = 'X';
  1565. break;
  1566. case 0x0000:
  1567. ch = 'T';
  1568. break;
  1569. default:
  1570. Error("Weird scancode value %04x: expected xx, E0xx or E1xx",
  1571. (Layout[idx].Scan & 0xFF00));
  1572. return FAILURE;
  1573. }
  1574. fprintf(pOut,
  1575. "#undef %c%02X\n"
  1576. "#define %c%02X _EQ(%43s%23s\n",
  1577. ch, LOBYTE(Layout[idx].Scan),
  1578. ch, LOBYTE(Layout[idx].Scan), getVKName(Layout[idx].VKey, 0), ")");
  1579. }
  1580. }
  1581. fprintf(pOut,"\n");
  1582. fclose(pOut);
  1583. return SUCCESS;
  1584. }
  1585. /*************************************************************\
  1586. * Convert a Unicode value to a text string
  1587. * Zero = 0 : return 'A'; 0x????
  1588. * 1 : return A ; \x????
  1589. * return : ptr to gCharName where result is stored
  1590. \*************************************************************/
  1591. char *WChName(int WC, int Zero)
  1592. {
  1593. char *s;
  1594. if(WC == -1)
  1595. {
  1596. strcpy(gCharName, "WCH_NONE");
  1597. }
  1598. else if(WC > 0x1F && WC < 0x7F)
  1599. {
  1600. s = gCharName;
  1601. if(Zero == 0)
  1602. {
  1603. *s++ = '\'';
  1604. }
  1605. if(WC == '\"' || WC == '\'' || WC == '\\')
  1606. {
  1607. *s++ = '\\';
  1608. }
  1609. *s++ = (char)WC;
  1610. if(Zero == 0)
  1611. {
  1612. *s++ = '\'';
  1613. }
  1614. *s = '\0';
  1615. }
  1616. else
  1617. {
  1618. switch (WC) {
  1619. case L'\r':
  1620. strcpy(gCharName, "'\\r'");
  1621. break;
  1622. case L'\n':
  1623. strcpy(gCharName, "'\\n'");
  1624. break;
  1625. case L'\b':
  1626. strcpy(gCharName, "'\\b'");
  1627. break;
  1628. default:
  1629. if(Zero == 0) {
  1630. sprintf(gCharName, "0x%04x", WC);
  1631. } else {
  1632. sprintf(gCharName, "\\x%04x", WC);
  1633. }
  1634. }
  1635. }
  1636. return gCharName;
  1637. }
  1638. void PrintNameTable(
  1639. FILE *pOut,
  1640. PKEYNAME pKN,
  1641. BOOL bDead)
  1642. {
  1643. char *p;
  1644. char *q;
  1645. int k;
  1646. char ExtraLine[LINEBUFSIZE];
  1647. while (pKN)
  1648. {
  1649. KEYNAME *pKNOld;
  1650. p = ExtraLine;
  1651. q = pKN->pName;
  1652. if (strncmp(q, "IDS_", 4) == 0) {
  1653. strcpy(p, "(LPWSTR)");
  1654. strcat(p, q);
  1655. } else {
  1656. *p++ = 'L';
  1657. if( *q != '\"' ) {
  1658. *p++ = '\"';
  1659. }
  1660. while(*q)
  1661. {
  1662. if( *q == '\\' && ( *(q+1) == 'x' || *(q+1) == 'X' ) )
  1663. {
  1664. while( *q == '\\' && ( *(q+1) == 'x' || *(q+1) == 'X' ) )
  1665. {
  1666. for(k = 0; *q && k < 6; k++)
  1667. {
  1668. *p++ = *q++;
  1669. }
  1670. }
  1671. if( *q )
  1672. {
  1673. *p++ = '\"';
  1674. *p++ = ' ';
  1675. *p++ = 'L';
  1676. *p++ = '\"';
  1677. }
  1678. }
  1679. else
  1680. {
  1681. *p++ = *q++;
  1682. }
  1683. }
  1684. if( *(p - 1) != '\"' )
  1685. {
  1686. *p++ = '\"';
  1687. }
  1688. *p++ = '\0';
  1689. }
  1690. if (bDead) {
  1691. fprintf(pOut," L\"%s\"\t%s,\n", WChName(pKN->Code, 1), ExtraLine);
  1692. } else {
  1693. fprintf(pOut," 0x%02x, %s,\n", pKN->Code, ExtraLine);
  1694. }
  1695. pKNOld = pKN;
  1696. pKN = pKN->pNext;
  1697. /*
  1698. * Free the memory (why bother???)
  1699. */
  1700. free(pKNOld->pName);
  1701. free(pKNOld);
  1702. }
  1703. if (bDead) {
  1704. fprintf(pOut," NULL\n");
  1705. } else {
  1706. fprintf(pOut," 0 , NULL\n");
  1707. }
  1708. }
  1709. /*************************************************************\
  1710. * write kbd*.c *
  1711. \*************************************************************/
  1712. int kbd_c(
  1713. int nState,
  1714. int aiState[],
  1715. char * szAttrs,
  1716. KEYLAYOUT Layout[],
  1717. PDEADKEY pDeadKey,
  1718. PLIGATURE pLigature,
  1719. PKEYNAME pKeyName,
  1720. PKEYNAME pKeyNameExt,
  1721. PKEYNAME pKeyNameDead)
  1722. {
  1723. char OutName[13];
  1724. char ExtraLine[LINEBUFSIZE];
  1725. char Tmp[WORDBUFSIZE];
  1726. char *p;
  1727. char *q;
  1728. FILE *pOut;
  1729. int MaxSt;
  1730. int aiSt[MAXSTATES];
  1731. int idx, idxSt, j, k, m;
  1732. DWORD dwEmptyTables = 0; // bitmask of empty VK_TO_WCHARS tables
  1733. KEYNAME *pKN;
  1734. DEADTRANS *pDeadTrans;
  1735. char *Cap[] = {
  1736. "0",
  1737. "CAPLOK",
  1738. "SGCAPS",
  1739. "CAPLOK | SGCAPS",
  1740. "CAPLOKALTGR",
  1741. "CAPLOK | CAPLOKALTGR"
  1742. };
  1743. strcpy(OutName, "KBD");
  1744. strcat(OutName, gKBDName);
  1745. strcat(OutName, ".C");
  1746. printf(" %12s", OutName);
  1747. if((pOut = fopen(OutName, "wt")) == NULL)
  1748. {
  1749. printf(": can't open for write\n");
  1750. return FAILURE;
  1751. }
  1752. fprintf(pOut,"/***************************************************************************\\\n"
  1753. "* Module Name: %s\n*\n* keyboard layout for %s\n"
  1754. "*\n"
  1755. "* Copyright (c) 1985-2001, Microsoft Corporation\n"
  1756. "*\n"
  1757. "* History:\n"
  1758. "* KBDTOOL v%d.%02d - Created %s"
  1759. "\\***************************************************************************/\n\n",
  1760. OutName, gDescription, gVersion, gSubVersion, asctime(Now)
  1761. );
  1762. if (fallback_driver) {
  1763. fprintf(pOut, "#include \"precomp.h\"\n");
  1764. }
  1765. else {
  1766. fprintf(pOut, "#include <windows.h>\n"
  1767. "#include \"kbd.h\"\n"
  1768. "#include \"kbd%s.h\"\n\n",
  1769. gKBDName);
  1770. }
  1771. if ( fallback_driver ) {
  1772. fprintf(pOut,"#pragma data_seg(\"%s\")\n"
  1773. "#define ALLOC_SECTION_LDATA"
  1774. #ifdef LATER
  1775. " const"
  1776. #endif
  1777. "\n\n",
  1778. ".kbdfallback" );
  1779. }
  1780. else {
  1781. fprintf(pOut,"#if defined(_M_IA64)\n"
  1782. "#pragma section(\"%s\")\n"
  1783. "#define ALLOC_SECTION_LDATA __declspec(allocate(\"%s\"))\n"
  1784. "#else\n"
  1785. "#pragma data_seg(\"%s\")\n"
  1786. "#define ALLOC_SECTION_LDATA\n"
  1787. "#endif\n\n",
  1788. ".data",
  1789. ".data",
  1790. ".data");
  1791. }
  1792. fprintf(pOut,"/***************************************************************************\\\n"
  1793. "* ausVK[] - Virtual Scan Code to Virtual Key conversion table for %s\n"
  1794. "\\***************************************************************************/\n\n"
  1795. ,gDescription);
  1796. fprintf(pOut,"static ALLOC_SECTION_LDATA USHORT ausVK[] = {\n"
  1797. " T00, T01, T02, T03, T04, T05, T06, T07,\n"
  1798. " T08, T09, T0A, T0B, T0C, T0D, T0E, T0F,\n"
  1799. " T10, T11, T12, T13, T14, T15, T16, T17,\n"
  1800. " T18, T19, T1A, T1B, T1C, T1D, T1E, T1F,\n"
  1801. " T20, T21, T22, T23, T24, T25, T26, T27,\n"
  1802. " T28, T29, T2A, T2B, T2C, T2D, T2E, T2F,\n"
  1803. " T30, T31, T32, T33, T34, T35,\n\n");
  1804. fprintf(pOut," /*\n"
  1805. " * Right-hand Shift key must have KBDEXT bit set.\n"
  1806. " */\n"
  1807. " T36 | KBDEXT,\n\n"
  1808. " T37 | KBDMULTIVK, // numpad_* + Shift/Alt -> SnapShot\n\n"
  1809. " T38, T39, T3A, T3B, T3C, T3D, T3E,\n"
  1810. " T3F, T40, T41, T42, T43, T44,\n\n");
  1811. fprintf(pOut," /*\n"
  1812. " * NumLock Key:\n"
  1813. " * KBDEXT - VK_NUMLOCK is an Extended key\n"
  1814. " * KBDMULTIVK - VK_NUMLOCK or VK_PAUSE (without or with CTRL)\n"
  1815. " */\n"
  1816. " T45 | KBDEXT | KBDMULTIVK,\n\n"
  1817. " T46 | KBDMULTIVK,\n\n");
  1818. fprintf(pOut," /*\n"
  1819. " * Number Pad keys:\n"
  1820. " * KBDNUMPAD - digits 0-9 and decimal point.\n"
  1821. " * KBDSPECIAL - require special processing by Windows\n"
  1822. " */\n"
  1823. " T47 | KBDNUMPAD | KBDSPECIAL, // Numpad 7 (Home)\n"
  1824. " T48 | KBDNUMPAD | KBDSPECIAL, // Numpad 8 (Up),\n"
  1825. " T49 | KBDNUMPAD | KBDSPECIAL, // Numpad 9 (PgUp),\n"
  1826. " T4A,\n"
  1827. " T4B | KBDNUMPAD | KBDSPECIAL, // Numpad 4 (Left),\n"
  1828. " T4C | KBDNUMPAD | KBDSPECIAL, // Numpad 5 (Clear),\n"
  1829. " T4D | KBDNUMPAD | KBDSPECIAL, // Numpad 6 (Right),\n"
  1830. " T4E,\n"
  1831. " T4F | KBDNUMPAD | KBDSPECIAL, // Numpad 1 (End),\n"
  1832. " T50 | KBDNUMPAD | KBDSPECIAL, // Numpad 2 (Down),\n"
  1833. " T51 | KBDNUMPAD | KBDSPECIAL, // Numpad 3 (PgDn),\n"
  1834. " T52 | KBDNUMPAD | KBDSPECIAL, // Numpad 0 (Ins),\n"
  1835. " T53 | KBDNUMPAD | KBDSPECIAL, // Numpad . (Del),\n\n");
  1836. fprintf(pOut," T54, T55, T56, T57, T58, T59, T5A, T5B,\n"
  1837. " T5C, T5D, T5E, T5F, T60, T61, T62, T63,\n"
  1838. " T64, T65, T66, T67, T68, T69, T6A, T6B,\n"
  1839. " T6C, T6D, T6E, T6F, T70, T71, T72, T73,\n"
  1840. " T74, T75, T76, T77, T78, T79, T7A, T7B,\n"
  1841. " T7C, T7D, T7E\n\n"
  1842. "};\n\n");
  1843. //
  1844. // Output E0-prefixed (extended) scancodes
  1845. //
  1846. fprintf(pOut,"static ALLOC_SECTION_LDATA VSC_VK aE0VscToVk[] = {\n");
  1847. for (idx = 0; idx < NUMSCVK; idx++) {
  1848. // skip keys that are not E0 extended
  1849. if ((Layout[idx].Scan & 0xFF00) != 0xE000) {
  1850. continue;
  1851. }
  1852. // if not undefined (Scan 0xffff) and not reserved (VKey 0xff)
  1853. if ((Layout[idx].Scan != 0xffff) && (Layout[idx].VKey != 0xff)) {
  1854. fprintf(pOut," { 0x%02X, X%02X | KBDEXT }, // %s\n",
  1855. Layout[idx].Scan & 0xFF, Layout[idx].Scan & 0xFF, Layout[idx].VKeyName);
  1856. }
  1857. }
  1858. fprintf(pOut," { 0, 0 }\n"
  1859. "};\n\n");
  1860. // Output 0xE1-prefixed scancodes
  1861. fprintf(pOut,"static ALLOC_SECTION_LDATA VSC_VK aE1VscToVk[] = {\n");
  1862. for (idx = 0; idx < NUMSCVK; idx++) {
  1863. // skip keys that are not E1 extended
  1864. if ((Layout[idx].Scan & 0xFF00) != 0xE100) {
  1865. continue;
  1866. }
  1867. // if not undefined (Scan 0xffff) and not reserved (VKey 0xff)
  1868. if ((Layout[idx].Scan != 0xffff) && (Layout[idx].VKey != 0xff)) {
  1869. fprintf(pOut," { 0x%02X, Y%02X | KBDEXT }, // %s\n",
  1870. Layout[idx].Scan & 0xFF, Layout[idx].Scan & 0xFF,
  1871. Layout[idx].VKeyName);
  1872. }
  1873. }
  1874. fprintf(pOut," { 0x1D, Y1D }, // Pause\n"
  1875. " { 0 , 0 }\n"
  1876. "};\n\n");
  1877. fprintf(pOut,"/***************************************************************************\\\n"
  1878. "* aVkToBits[] - map Virtual Keys to Modifier Bits\n"
  1879. "*\n"
  1880. "* See kbd.h for a full description.\n"
  1881. "*\n"
  1882. "* %s Keyboard has only three shifter keys:\n"
  1883. "* SHIFT (L & R) affects alphabnumeric keys,\n"
  1884. "* CTRL (L & R) is used to generate control characters\n"
  1885. "* ALT (L & R) used for generating characters by number with numpad\n"
  1886. "\\***************************************************************************/\n"
  1887. ,gDescription);
  1888. // if (we get an RCONTROL, change VK_CONTROL to be VK_LCONTROL) { same for RMENU, RSHIFT?
  1889. // } CAN/CSA tap selection....
  1890. fprintf(pOut,"static ALLOC_SECTION_LDATA VK_TO_BIT aVkToBits[] = {\n");
  1891. for (idx = 0; Modifiers[idx].Vk != 0; idx++) {
  1892. fprintf(pOut, " { %-12s, %-12s },\n",
  1893. getVKName(Modifiers[idx].Vk, TRUE),
  1894. Modifiers[idx].pszModBits);
  1895. }
  1896. fprintf(pOut, " { 0 , 0 }\n};\n\n");
  1897. fprintf(pOut,"/***************************************************************************\\\n"
  1898. "* aModification[] - map character modifier bits to modification number\n"
  1899. "*\n"
  1900. "* See kbd.h for a full description.\n"
  1901. "*\n"
  1902. "\\***************************************************************************/\n\n");
  1903. for (idxSt = 0; idxSt < MAXSTATES; idxSt++) {
  1904. aiSt[idxSt] = -1;
  1905. }
  1906. MaxSt = 1;
  1907. for (idxSt = 0; idxSt < MAXSTATES && aiState[idxSt] > -1; idxSt++) {
  1908. aiSt[aiState[idxSt]] = idxSt;
  1909. if (aiState[idxSt] > MaxSt) {
  1910. MaxSt = aiState[idxSt];
  1911. }
  1912. }
  1913. fprintf(pOut,"static ALLOC_SECTION_LDATA MODIFIERS CharModifiers = {\n"
  1914. " &aVkToBits[0],\n"
  1915. " %d,\n"
  1916. " {\n"
  1917. " // Modification# // Keys Pressed\n"
  1918. " // ============= // =============\n"
  1919. ,MaxSt);
  1920. for (idxSt = 0; idxSt <= MaxSt; idxSt++) {
  1921. int iMod;
  1922. BOOL bNeedPlus;
  1923. if(aiSt[idxSt] == -1) {
  1924. fprintf(pOut," SHFT_INVALID, // ");
  1925. } else if(idxSt == MaxSt) {
  1926. fprintf(pOut," %d // ", aiSt[idxSt]);
  1927. } else {
  1928. fprintf(pOut," %d, // ", aiSt[idxSt]);
  1929. }
  1930. bNeedPlus = FALSE;
  1931. for (iMod = 0; (1 << iMod) <= idxSt; iMod++) {
  1932. if (bNeedPlus) {
  1933. fprintf(pOut, "+ ");
  1934. bNeedPlus = FALSE;
  1935. }
  1936. if ((1 << iMod) & idxSt) {
  1937. char achModifier[50];
  1938. strcpy(achModifier, getVKName(Modifiers[iMod].Vk, TRUE));
  1939. for (j = 4; (j < 50) && (achModifier[j] != '\0'); j++) {
  1940. achModifier[j] = (char)tolower(achModifier[j]);
  1941. }
  1942. fprintf(pOut, "%s ", &achModifier[3]);
  1943. bNeedPlus = TRUE;
  1944. }
  1945. }
  1946. fprintf(pOut, "\n");
  1947. }
  1948. fprintf(pOut," }\n"
  1949. "};\n\n");
  1950. fprintf(pOut,"/***************************************************************************\\\n"
  1951. "*\n"
  1952. "* aVkToWch2[] - Virtual Key to WCHAR translation for 2 shift states\n"
  1953. "* aVkToWch3[] - Virtual Key to WCHAR translation for 3 shift states\n"
  1954. "* aVkToWch4[] - Virtual Key to WCHAR translation for 4 shift states\n");
  1955. for (idxSt = 5; idxSt < MaxSt; idxSt++) {
  1956. fprintf(pOut,
  1957. "* aVkToWch%d[] - Virtual Key to WCHAR translation for %d shift states\n",
  1958. idxSt, idxSt);
  1959. }
  1960. fprintf(pOut,"*\n"
  1961. "* Table attributes: Unordered Scan, null-terminated\n"
  1962. "*\n"
  1963. "* Search this table for an entry with a matching Virtual Key to find the\n"
  1964. "* corresponding unshifted and shifted WCHAR characters.\n"
  1965. "*\n"
  1966. "* Special values for VirtualKey (column 1)\n"
  1967. "* 0xff - dead chars for the previous entry\n"
  1968. "* 0 - terminate the list\n"
  1969. "*\n"
  1970. "* Special values for Attributes (column 2)\n"
  1971. "* CAPLOK bit - CAPS-LOCK affect this key like SHIFT\n"
  1972. "*\n"
  1973. "* Special values for wch[*] (column 3 & 4)\n"
  1974. "* WCH_NONE - No character\n"
  1975. "* WCH_DEAD - Dead Key (diaresis) or invalid (US keyboard has none)\n"
  1976. "* WCH_LGTR - Ligature (generates multiple characters)\n"
  1977. "*\n"
  1978. "\\***************************************************************************/\n\n");
  1979. for (idxSt = 2; idxSt <= nState; idxSt++) {
  1980. /*
  1981. * Quickly check if this table would actually be empty.
  1982. * An empty table (containing just zero terminator) is pointless.
  1983. * Also it will go into the .bss section, which we would have to merge
  1984. * into the .data section with a linker flag, else NT wouldn't load it
  1985. * (bug #120244 - IanJa)
  1986. */
  1987. BOOL bEmpty;
  1988. bEmpty = TRUE;
  1989. if (idxSt == 2) {
  1990. // Special case for TAB ADD DIVIDE MULTIPLY SUBTRACT (below)
  1991. bEmpty = FALSE;
  1992. } else {
  1993. for (j = 0; j < NUMSCVK; j++) {
  1994. if (Layout[j].nState == idxSt) {
  1995. bEmpty = FALSE;
  1996. break;
  1997. }
  1998. }
  1999. }
  2000. if (bEmpty) {
  2001. fprintf(stderr, "\ntable %d is empty\n", idxSt);
  2002. dwEmptyTables |= (1 << idxSt);
  2003. continue;
  2004. }
  2005. fprintf(pOut,"static ALLOC_SECTION_LDATA VK_TO_WCHARS%d aVkToWch%d[] = {\n"
  2006. "// | | Shift |"
  2007. ,idxSt, idxSt);
  2008. for (j = 2; j < idxSt; j++) {
  2009. fprintf(pOut,"%-9.9s|", StateLabel[aiState[j]]);
  2010. }
  2011. fprintf(pOut,"\n// |=========|=========|");
  2012. for(j = 2; j < idxSt; j++) {
  2013. fprintf(pOut,"=========|");
  2014. }
  2015. fprintf(pOut,"\n");
  2016. for (j = 0; j < NUMSCVK; j++) {
  2017. if (idxSt != Layout[j].nState) {
  2018. continue;
  2019. }
  2020. fprintf(pOut," {%-13s,%-7s", \
  2021. getVKName(Layout[j].VKey, 1), Cap[Layout[j].Cap]);
  2022. *ExtraLine = '\0';
  2023. for (k = 0; k < idxSt; k++) {
  2024. if (pDeadKey != NULL && Layout[j].DKy[k] == 1) {
  2025. /*
  2026. * it is a dead key
  2027. */
  2028. if (*ExtraLine == '\0') {
  2029. strcpy(ExtraLine, " {0xff ,0 ");
  2030. if (Layout[j].Cap != 2) {
  2031. /*
  2032. * Not SGCap
  2033. */
  2034. for (m = 0; m < k; m++) {
  2035. strcat(ExtraLine, ",WCH_NONE ");
  2036. }
  2037. } else {
  2038. /*
  2039. * added for a new kbdCZ that has both SGCap and WCH_DEAD
  2040. */
  2041. for (m = 0; m < k; m++ ) {
  2042. if (Layout[j].pSGCAP->WCh[m] == 0) {
  2043. strcat( ExtraLine, ",WCH_NONE " );
  2044. } else {
  2045. sprintf( Tmp, ",%-9s", WChName( Layout[j].pSGCAP->WCh[m], 0 ) );
  2046. strcat( ExtraLine, Tmp );
  2047. }
  2048. }
  2049. }
  2050. }
  2051. sprintf(Tmp,",%-9s", WChName(Layout[j].WCh[k], 0));
  2052. strcat(ExtraLine, Tmp);
  2053. fprintf(pOut,",WCH_DEAD ");
  2054. } else if(Layout[j].LKy[k] == 1) {
  2055. /*
  2056. * it is a ligature key
  2057. */
  2058. if (pLigature == NULL) {
  2059. Error("Ligature entry with no LIGATURE table");
  2060. fclose(pOut);
  2061. return FAILURE;
  2062. }
  2063. fprintf(pOut,",WCH_LGTR ");
  2064. if (*ExtraLine != '\0') {
  2065. strcat(ExtraLine, ",WCH_NONE ");
  2066. }
  2067. } else {
  2068. fprintf(pOut,",%-9s", WChName(Layout[j].WCh[k], 0));
  2069. if (*ExtraLine != '\0') {
  2070. strcat(ExtraLine, ",WCH_NONE ");
  2071. }
  2072. }
  2073. }
  2074. fprintf(pOut,"},\n");
  2075. if (*ExtraLine != '\0') {
  2076. fprintf(pOut,"%s},\n", ExtraLine);
  2077. continue; /* skip if WCH_DEAD */
  2078. }
  2079. /*
  2080. * skip if not SGCAP
  2081. */
  2082. if (Layout[j].Cap != 2) {
  2083. continue;
  2084. }
  2085. if (Layout[j].pSGCAP == NULL) {
  2086. fclose(pOut);
  2087. Error("failed SGCAP error");
  2088. return FAILURE;
  2089. }
  2090. fprintf(pOut," {%-13s,0 ", getVKName(Layout[j].VKey, 1));
  2091. for (k = 0; k < Layout[j].pSGCAP->nState; k++) {
  2092. fprintf(pOut,",%-9s", WChName(Layout[j].pSGCAP->WCh[k], 0));
  2093. }
  2094. fprintf(pOut,"},\n");
  2095. free (Layout[j].pSGCAP);
  2096. }
  2097. /*
  2098. * These entries appear last to make VkKeyScan[Ex] results match
  2099. * Windows 95/98. See DRIVERS\KEYBOARD\WIN3.1\TAB4.INC (under
  2100. * \\redrum\w98slmRO\proj\dos\src)
  2101. */
  2102. if (idxSt == 2) {
  2103. fprintf(pOut," {VK_TAB ,0 ,'\\t' ,'\\t' },\n"
  2104. " {VK_ADD ,0 ,'+' ,'+' },\n"
  2105. " {VK_DIVIDE ,0 ,'/' ,'/' },\n"
  2106. " {VK_MULTIPLY ,0 ,'*' ,'*' },\n"
  2107. " {VK_SUBTRACT ,0 ,'-' ,'-' },\n");
  2108. }
  2109. fprintf(pOut," {0 ,0 ");
  2110. for (k = 0; k < idxSt; k++) {
  2111. fprintf(pOut,",0 ");
  2112. }
  2113. fprintf(pOut,"}\n"
  2114. "};\n\n");
  2115. }
  2116. fprintf(pOut,"// Put this last so that VkKeyScan interprets number characters\n"
  2117. "// as coming from the main section of the kbd (aVkToWch2 and\n"
  2118. "// aVkToWch5) before considering the numpad (aVkToWch1).\n\n"
  2119. "static ALLOC_SECTION_LDATA VK_TO_WCHARS1 aVkToWch1[] = {\n"
  2120. " { VK_NUMPAD0 , 0 , '0' },\n"
  2121. " { VK_NUMPAD1 , 0 , '1' },\n"
  2122. " { VK_NUMPAD2 , 0 , '2' },\n"
  2123. " { VK_NUMPAD3 , 0 , '3' },\n"
  2124. " { VK_NUMPAD4 , 0 , '4' },\n"
  2125. " { VK_NUMPAD5 , 0 , '5' },\n"
  2126. " { VK_NUMPAD6 , 0 , '6' },\n"
  2127. " { VK_NUMPAD7 , 0 , '7' },\n"
  2128. " { VK_NUMPAD8 , 0 , '8' },\n"
  2129. " { VK_NUMPAD9 , 0 , '9' },\n"
  2130. " { 0 , 0 , '\\0' }\n"
  2131. "};\n\n");
  2132. fprintf(pOut,"static ALLOC_SECTION_LDATA VK_TO_WCHAR_TABLE aVkToWcharTable[] = {\n");
  2133. for (idxSt = 3; idxSt <= nState; idxSt++) {
  2134. if ((dwEmptyTables & (1 << idxSt)) == 0) {
  2135. fprintf(pOut,
  2136. " { (PVK_TO_WCHARS1)aVkToWch%d, %d, sizeof(aVkToWch%d[0]) },\n",
  2137. idxSt, idxSt, idxSt);
  2138. }
  2139. }
  2140. fprintf(pOut," { (PVK_TO_WCHARS1)aVkToWch2, 2, sizeof(aVkToWch2[0]) },\n"
  2141. " { (PVK_TO_WCHARS1)aVkToWch1, 1, sizeof(aVkToWch1[0]) },\n"
  2142. " { NULL, 0, 0 },\n"
  2143. "};\n\n");
  2144. fprintf(pOut,"/***************************************************************************\\\n"
  2145. "* aKeyNames[], aKeyNamesExt[] - Virtual Scancode to Key Name tables\n"
  2146. "*\n"
  2147. "* Table attributes: Ordered Scan (by scancode), null-terminated\n"
  2148. "*\n"
  2149. "* Only the names of Extended, NumPad, Dead and Non-Printable keys are here.\n"
  2150. "* (Keys producing printable characters are named by that character)\n"
  2151. "\\***************************************************************************/\n\n");
  2152. if (pKeyName != NULL) {
  2153. fprintf(pOut,"static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNames[] = {\n");
  2154. PrintNameTable(pOut, pKeyName, FALSE);
  2155. fprintf(pOut,"};\n\n");
  2156. }
  2157. if (pKeyNameExt != NULL) {
  2158. fprintf(pOut,"static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNamesExt[] = {\n");
  2159. PrintNameTable(pOut, pKeyNameExt, FALSE);
  2160. fprintf(pOut,"};\n\n");
  2161. }
  2162. if (pKeyNameDead != NULL) {
  2163. if (pDeadKey == NULL) {
  2164. fprintf(pOut,"/*** No dead key defined, dead key names ignored ! ***\\\n\n");
  2165. }
  2166. fprintf(pOut,"static ALLOC_SECTION_LDATA DEADKEY_LPWSTR aKeyNamesDead[] = {\n");
  2167. PrintNameTable(pOut, pKeyNameDead, TRUE);
  2168. fprintf(pOut,"};\n\n");
  2169. if(pDeadKey == NULL) {
  2170. fprintf(pOut,"\\*****************************************************/\n\n");
  2171. }
  2172. }
  2173. if (pDeadKey != NULL) {
  2174. PDEADKEY pDeadKeyTmp = pDeadKey;
  2175. fprintf(pOut,"static ALLOC_SECTION_LDATA DEADKEY aDeadKey[] = {\n");
  2176. while (pDeadKeyTmp != NULL) {
  2177. PDEADKEY pDeadKeyOld;
  2178. pDeadTrans = pDeadKeyTmp->pDeadTrans;
  2179. while (pDeadTrans != NULL) {
  2180. PDEADTRANS pDeadTransOld;
  2181. fprintf(pOut," DEADTRANS( ");
  2182. if (strlen(WChName(pDeadTrans->Base, 0)) == 3) {
  2183. fprintf(pOut,"L%-6s, ", WChName(pDeadTrans->Base, 0));
  2184. } else {
  2185. fprintf(pOut,"%-7s, ", WChName(pDeadTrans->Base, 0));
  2186. }
  2187. if (strlen(WChName(pDeadKeyTmp->Dead, 0)) == 3) {
  2188. fprintf(pOut,"L%-6s, ", WChName(pDeadKeyTmp->Dead, 0));
  2189. } else {
  2190. fprintf(pOut,"%-7s, ", WChName(pDeadKeyTmp->Dead, 0));
  2191. }
  2192. if (strlen(WChName(pDeadTrans->WChar, 0)) == 3) {
  2193. fprintf(pOut,"L%-6s, ", WChName(pDeadTrans->WChar, 0));
  2194. } else {
  2195. fprintf(pOut,"%-7s, ", WChName(pDeadTrans->WChar, 0));
  2196. }
  2197. fprintf(pOut,"0x%04x),\n", pDeadTrans->uFlags);
  2198. pDeadTransOld = pDeadTrans;
  2199. pDeadTrans = pDeadTrans->pNext;
  2200. free(pDeadTransOld);
  2201. }
  2202. fprintf(pOut,"\n");
  2203. pDeadKeyOld = pDeadKeyTmp;
  2204. pDeadKeyTmp = pDeadKeyTmp->pNext;
  2205. free(pDeadKeyOld);
  2206. }
  2207. fprintf(pOut," 0, 0\n");
  2208. fprintf(pOut,"};\n\n");
  2209. }
  2210. if (pLigature != NULL) {
  2211. PLIGATURE pLigatureTmp = pLigature;
  2212. fprintf(pOut,"static ALLOC_SECTION_LDATA LIGATURE%d aLigature[] = {\n", gMaxLigature);
  2213. while (pLigatureTmp != NULL) {
  2214. PLIGATURE pLigatureOld;
  2215. fprintf(pOut," {%-13s,%-7d", \
  2216. getVKName(pLigatureTmp->VKey, 1), pLigatureTmp->Mod);
  2217. for (k = 0; k < gMaxLigature; k++) {
  2218. if (k < pLigatureTmp->nCharacters) {
  2219. fprintf(pOut,",%-9s", WChName(pLigatureTmp->WCh[k], 0));
  2220. } else {
  2221. fprintf(pOut,",WCH_NONE ");
  2222. }
  2223. }
  2224. fprintf(pOut,"},\n");
  2225. pLigatureOld = pLigatureTmp;
  2226. pLigatureTmp = pLigatureTmp->pNext;
  2227. free(pLigatureOld);
  2228. }
  2229. fprintf(pOut," {%-13d,%-7d", 0, 0);
  2230. for (k = 0; k < gMaxLigature; k++) {
  2231. fprintf(pOut,",%-9d", 0);
  2232. }
  2233. fprintf(pOut,"}\n};\n\n");
  2234. }
  2235. if (!fallback_driver) {
  2236. fprintf(pOut, "static ");
  2237. }
  2238. fprintf(pOut,"ALLOC_SECTION_LDATA KBDTABLES KbdTables%s = {\n"
  2239. " /*\n"
  2240. " * Modifier keys\n"
  2241. " */\n"
  2242. " &CharModifiers,\n\n"
  2243. " /*\n"
  2244. " * Characters tables\n"
  2245. " */\n"
  2246. " aVkToWcharTable,\n\n"
  2247. " /*\n"
  2248. " * Diacritics\n"
  2249. " */\n",
  2250. fallback_driver ? "Fallback" : "");
  2251. if (pDeadKey != NULL) {
  2252. fprintf(pOut," aDeadKey,\n\n");
  2253. } else {
  2254. fprintf(pOut," NULL,\n\n");
  2255. }
  2256. fprintf(pOut," /*\n"
  2257. " * Names of Keys\n"
  2258. " */\n");
  2259. if (pKeyName != NULL) {
  2260. fprintf(pOut," aKeyNames,\n");
  2261. } else {
  2262. fprintf(pOut," NULL,\n");
  2263. }
  2264. if (pKeyNameExt != NULL) {
  2265. fprintf(pOut," aKeyNamesExt,\n");
  2266. } else {
  2267. fprintf(pOut," NULL,\n");
  2268. }
  2269. if (pDeadKey != NULL && pKeyNameDead != NULL) {
  2270. fprintf(pOut," aKeyNamesDead,\n\n");
  2271. } else {
  2272. fprintf(pOut," NULL,\n\n");
  2273. }
  2274. fprintf(pOut," /*\n"
  2275. " * Scan codes to Virtual Keys\n"
  2276. " */\n"
  2277. " ausVK,\n"
  2278. " sizeof(ausVK) / sizeof(ausVK[0]),\n"
  2279. " aE0VscToVk,\n"
  2280. " aE1VscToVk,\n\n"
  2281. " /*\n"
  2282. " * Locale-specific special processing\n"
  2283. " */\n");
  2284. if (MaxSt > 5) {
  2285. if (szAttrs[0] != '\0') {
  2286. strcat(szAttrs, " | ");
  2287. }
  2288. strcat(szAttrs, "KLLF_ALTGR");
  2289. } else if (szAttrs[0] == '\0') {
  2290. strcpy(szAttrs, "0");
  2291. }
  2292. fprintf(pOut," MAKELONG(%s, KBD_VERSION),\n\n", szAttrs);
  2293. fprintf(pOut," /*\n"
  2294. " * Ligatures\n"
  2295. " */\n"
  2296. " %d,\n", gMaxLigature);
  2297. if (pLigature != NULL) {
  2298. fprintf(pOut," sizeof(aLigature[0]),\n");
  2299. fprintf(pOut," (PLIGATURE1)aLigature\n");
  2300. } else {
  2301. fprintf(pOut," 0,\n");
  2302. fprintf(pOut," NULL\n");
  2303. }
  2304. fprintf(pOut, "};\n\n");
  2305. if (!fallback_driver) {
  2306. fprintf(pOut,"PKBDTABLES KbdLayerDescriptor(VOID)\n"
  2307. "{\n"
  2308. " return &KbdTables;\n"
  2309. "}\n");
  2310. }
  2311. fclose(pOut);
  2312. return SUCCESS;
  2313. }
  2314. /*****************************************************************************\
  2315. * read next (content-containing) line from input file
  2316. * Consumes lines the are empty, or contain just comments.
  2317. *
  2318. * Buf - contains the new line.
  2319. * (A nul character is inserted before any comment portion)
  2320. * cchBuf - provides number of characters in Buf
  2321. * gLineCount - Incremented for each line read (including skipped lines)
  2322. *
  2323. * Returns TRUE - if new line is returned in Buf
  2324. * FALSE - if end of file was reached
  2325. \*****************************************************************************/
  2326. BOOL NextLine(char *Buf, DWORD cchBuf, FILE *fIn)
  2327. {
  2328. char *p;
  2329. char *pComment;
  2330. while (fgets(Buf, cchBuf, fIn) != NULL) {
  2331. gLineCount++;
  2332. p = Buf;
  2333. // skip leading white spaces
  2334. while( *p && (*p == ' ' || *p == '\t')) {
  2335. p++;
  2336. }
  2337. if (*p == ';') {
  2338. // This line is purely comment, so skip it
  2339. continue;
  2340. }
  2341. if ((pComment = strstr(p, "//")) != NULL) {
  2342. if (pComment == p) {
  2343. // This line is purely comment, so skip it
  2344. continue;
  2345. }
  2346. // separate comment portion from content-containing portion
  2347. *pComment = '\0';
  2348. } else {
  2349. // remove newline at the end
  2350. if ((p = strchr(p, '\n')) != NULL) {
  2351. *p = '\0';
  2352. }
  2353. }
  2354. // We are returning a content-containing line
  2355. return TRUE;
  2356. }
  2357. // we reached the end of the file
  2358. return FALSE;
  2359. }
  2360. VOID __cdecl Error(const char *Text, ... )
  2361. {
  2362. char Temp[1024];
  2363. va_list valist;
  2364. va_start(valist, Text);
  2365. vsprintf(Temp,Text,valist);
  2366. printf("\n%s(%d): error : %s\n", gpszFileName, gLineCount, Temp);
  2367. va_end(valist);
  2368. exit(EXIT_FAILURE);
  2369. }
  2370. ULONG __cdecl Warning(int nLine, const char *Text, ... )
  2371. {
  2372. char Temp[1024];
  2373. va_list valist;
  2374. if (nLine == 0) {
  2375. nLine = gLineCount;
  2376. }
  2377. va_start(valist, Text);
  2378. vsprintf(Temp,Text,valist);
  2379. printf("%s(%d): warning - %s\n", gpszFileName, nLine, Temp);
  2380. va_end(valist);
  2381. return 0;
  2382. }
  2383. VOID DumpLayoutEntry(PKEYLAYOUT pLayout)
  2384. {
  2385. printf("Scan %2x, VK %2x, VKDef %2x, Cap %d, nState %d, defined %x\n",
  2386. pLayout->Scan,
  2387. pLayout->VKey,
  2388. pLayout->VKeyDefault,
  2389. pLayout->Cap,
  2390. pLayout->nState,
  2391. pLayout->defined
  2392. );
  2393. printf("WCh[] = %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
  2394. pLayout->WCh[0], pLayout->WCh[1],
  2395. pLayout->WCh[2], pLayout->WCh[3],
  2396. pLayout->WCh[4], pLayout->WCh[5],
  2397. pLayout->WCh[6], pLayout->WCh[7],
  2398. pLayout->WCh[8]);
  2399. printf("DKy[] = %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
  2400. pLayout->DKy[0], pLayout->DKy[1],
  2401. pLayout->DKy[2], pLayout->DKy[3],
  2402. pLayout->DKy[4], pLayout->DKy[5],
  2403. pLayout->DKy[6], pLayout->DKy[7],
  2404. pLayout->DKy[8]);
  2405. printf("LKy[] = %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
  2406. pLayout->LKy[0], pLayout->LKy[1],
  2407. pLayout->LKy[2], pLayout->LKy[3],
  2408. pLayout->LKy[4], pLayout->LKy[5],
  2409. pLayout->LKy[6], pLayout->LKy[7],
  2410. pLayout->LKy[8]);
  2411. printf("pSGCAP = %p\n", pLayout->pSGCAP);
  2412. printf("VKeyName = %s\n", pLayout->VKeyName);
  2413. }
  2414. /*
  2415. * Helper routine to make sure Backspace, Enter, Esc, Space and Cancel
  2416. * have the right characters.
  2417. * If they aren't defined by the input file, this is where we set their
  2418. * default values.
  2419. */
  2420. BOOL MergeState(
  2421. KEYLAYOUT Layout[],
  2422. int Vk,
  2423. WCHAR wchUnshifted,
  2424. WCHAR wchShifted,
  2425. WCHAR wchCtrl,
  2426. int aiState[],
  2427. int nState)
  2428. {
  2429. static int idxCtrl = -1;
  2430. int idxSt, idx;
  2431. PKEYLAYOUT pLayout = NULL;
  2432. // which state is Ctrl?
  2433. if (idxCtrl == -1) {
  2434. for (idxSt = 0; idxSt < nState; idxSt++) {
  2435. if (aiState[idxSt] == KBDCTRL) {
  2436. idxCtrl = idxSt;
  2437. break;
  2438. }
  2439. }
  2440. }
  2441. if (idxCtrl == -1) {
  2442. Error("No Ctrl state");
  2443. }
  2444. // find the VK we want to merge
  2445. for (idx = 0; idx < NUMSCVK; idx++) {
  2446. if (Layout[idx].VKey == Vk) {
  2447. pLayout = &Layout[idx];
  2448. break;
  2449. }
  2450. }
  2451. if (pLayout == NULL) {
  2452. Error("No VK %2x state", Vk);
  2453. }
  2454. /*
  2455. * Now merge the default values in
  2456. */
  2457. // printf("BEFORE ====================\n");
  2458. // DumpLayoutEntry(pLayout);
  2459. if (pLayout->WCh[0] == 0) {
  2460. pLayout->WCh[0] = wchUnshifted;
  2461. }
  2462. if (pLayout->WCh[1] == 0) {
  2463. pLayout->WCh[1] = wchShifted;
  2464. }
  2465. if (pLayout->WCh[idxCtrl] == 0) {
  2466. pLayout->WCh[idxCtrl] = wchCtrl;
  2467. }
  2468. // pad empty slots with WCH_NONE
  2469. for (idxSt = pLayout->nState; idxSt < idxCtrl; idxSt++) {
  2470. if (pLayout->WCh[idxSt] == 0) {
  2471. pLayout->WCh[idxSt] = -1; // WCH_NONE
  2472. }
  2473. }
  2474. if (pLayout->nState <= idxCtrl) {
  2475. pLayout->nState = idxCtrl + 1;
  2476. }
  2477. pLayout->defined = TRUE;
  2478. // printf("AFTER ===================\n");
  2479. // DumpLayoutEntry(pLayout);
  2480. // printf("=========================\n\n");
  2481. return TRUE;
  2482. }