genkeysymdef.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env node
  2. /*
  3. * genkeysymdef: X11 keysymdef.h to JavaScript converter
  4. * Copyright (C) 2018 The noVNC Authors
  5. * Licensed under MPL 2.0 (see LICENSE.txt)
  6. */
  7. "use strict";
  8. const fs = require('fs');
  9. let showHelp = process.argv.length === 2;
  10. let filename;
  11. for (let i = 2; i < process.argv.length; ++i) {
  12. switch (process.argv[i]) {
  13. case "--help":
  14. case "-h":
  15. showHelp = true;
  16. break;
  17. case "--file":
  18. case "-f":
  19. default:
  20. filename = process.argv[i];
  21. }
  22. }
  23. if (!filename) {
  24. showHelp = true;
  25. console.log("Error: No filename specified\n");
  26. }
  27. if (showHelp) {
  28. console.log("Parses a *nix keysymdef.h to generate Unicode code point mappings");
  29. console.log("Usage: node parse.js [options] filename:");
  30. console.log(" -h [ --help ] Produce this help message");
  31. console.log(" filename The keysymdef.h file to parse");
  32. process.exit(0);
  33. }
  34. const buf = fs.readFileSync(filename);
  35. const str = buf.toString('utf8');
  36. const re = /^#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/m;
  37. const arr = str.split('\n');
  38. const codepoints = {};
  39. for (let i = 0; i < arr.length; ++i) {
  40. const result = re.exec(arr[i]);
  41. if (result) {
  42. const keyname = result[1];
  43. const keysym = parseInt(result[2], 16);
  44. const remainder = result[3];
  45. const unicodeRes = /U\+([0-9a-fA-F]+)/.exec(remainder);
  46. if (unicodeRes) {
  47. const unicode = parseInt(unicodeRes[1], 16);
  48. // The first entry is the preferred one
  49. if (!codepoints[unicode]) {
  50. codepoints[unicode] = { keysym: keysym, name: keyname };
  51. }
  52. }
  53. }
  54. }
  55. let out =
  56. "/*\n" +
  57. " * Mapping from Unicode codepoints to X11/RFB keysyms\n" +
  58. " *\n" +
  59. " * This file was automatically generated from keysymdef.h\n" +
  60. " * DO NOT EDIT!\n" +
  61. " */\n" +
  62. "\n" +
  63. "/* Functions at the bottom */\n" +
  64. "\n" +
  65. "const codepoints = {\n";
  66. function toHex(num) {
  67. let s = num.toString(16);
  68. if (s.length < 4) {
  69. s = ("0000" + s).slice(-4);
  70. }
  71. return "0x" + s;
  72. }
  73. for (let codepoint in codepoints) {
  74. codepoint = parseInt(codepoint);
  75. // Latin-1?
  76. if ((codepoint >= 0x20) && (codepoint <= 0xff)) {
  77. continue;
  78. }
  79. // Handled by the general Unicode mapping?
  80. if ((codepoint | 0x01000000) === codepoints[codepoint].keysym) {
  81. continue;
  82. }
  83. out += " " + toHex(codepoint) + ": " +
  84. toHex(codepoints[codepoint].keysym) +
  85. ", // XK_" + codepoints[codepoint].name + "\n";
  86. }
  87. out +=
  88. "};\n" +
  89. "\n" +
  90. "export default {\n" +
  91. " lookup(u) {\n" +
  92. " // Latin-1 is one-to-one mapping\n" +
  93. " if ((u >= 0x20) && (u <= 0xff)) {\n" +
  94. " return u;\n" +
  95. " }\n" +
  96. "\n" +
  97. " // Lookup table (fairly random)\n" +
  98. " const keysym = codepoints[u];\n" +
  99. " if (keysym !== undefined) {\n" +
  100. " return keysym;\n" +
  101. " }\n" +
  102. "\n" +
  103. " // General mapping as final fallback\n" +
  104. " return 0x01000000 | u;\n" +
  105. " },\n" +
  106. "};";
  107. console.log(out);