#!/usr/bin/env node /* * genkeysymdef: X11 keysymdef.h to JavaScript converter * Copyright (C) 2018 The noVNC Authors * Licensed under MPL 2.0 (see LICENSE.txt) */ "use strict"; const fs = require('fs'); let showHelp = process.argv.length === 2; let filename; for (let i = 2; i < process.argv.length; ++i) { switch (process.argv[i]) { case "--help": case "-h": showHelp = true; break; case "--file": case "-f": default: filename = process.argv[i]; } } if (!filename) { showHelp = true; console.log("Error: No filename specified\n"); } if (showHelp) { console.log("Parses a *nix keysymdef.h to generate Unicode code point mappings"); console.log("Usage: node parse.js [options] filename:"); console.log(" -h [ --help ] Produce this help message"); console.log(" filename The keysymdef.h file to parse"); process.exit(0); } const buf = fs.readFileSync(filename); const str = buf.toString('utf8'); const re = /^#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/m; const arr = str.split('\n'); const codepoints = {}; for (let i = 0; i < arr.length; ++i) { const result = re.exec(arr[i]); if (result) { const keyname = result[1]; const keysym = parseInt(result[2], 16); const remainder = result[3]; const unicodeRes = /U\+([0-9a-fA-F]+)/.exec(remainder); if (unicodeRes) { const unicode = parseInt(unicodeRes[1], 16); // The first entry is the preferred one if (!codepoints[unicode]) { codepoints[unicode] = { keysym: keysym, name: keyname }; } } } } let out = "/*\n" + " * Mapping from Unicode codepoints to X11/RFB keysyms\n" + " *\n" + " * This file was automatically generated from keysymdef.h\n" + " * DO NOT EDIT!\n" + " */\n" + "\n" + "/* Functions at the bottom */\n" + "\n" + "const codepoints = {\n"; function toHex(num) { let s = num.toString(16); if (s.length < 4) { s = ("0000" + s).slice(-4); } return "0x" + s; } for (let codepoint in codepoints) { codepoint = parseInt(codepoint); // Latin-1? if ((codepoint >= 0x20) && (codepoint <= 0xff)) { continue; } // Handled by the general Unicode mapping? if ((codepoint | 0x01000000) === codepoints[codepoint].keysym) { continue; } out += " " + toHex(codepoint) + ": " + toHex(codepoints[codepoint].keysym) + ", // XK_" + codepoints[codepoint].name + "\n"; } out += "};\n" + "\n" + "export default {\n" + " lookup(u) {\n" + " // Latin-1 is one-to-one mapping\n" + " if ((u >= 0x20) && (u <= 0xff)) {\n" + " return u;\n" + " }\n" + "\n" + " // Lookup table (fairly random)\n" + " const keysym = codepoints[u];\n" + " if (keysym !== undefined) {\n" + " return keysym;\n" + " }\n" + "\n" + " // General mapping as final fallback\n" + " return 0x01000000 | u;\n" + " },\n" + "};"; console.log(out);