Merge pull request #9075 from keymanapp/fix/developer/kmc-kmw-options-stores

fix(developer): support option stores in kmc-kmn/kmw 🗜
This commit is contained in:
Marc Durdin 2023-06-26 17:27:41 +10:00 committed by GitHub
commit c3bb426ff0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1049 additions and 149 deletions

View file

@ -17,6 +17,22 @@ export interface CompilerResultFile {
data: Uint8Array;
};
//
// Matches kmcmplibapi.h definitions
//
export const STORETYPE_STORE = 0x01;
export const STORETYPE_RESERVED = 0x02;
export const STORETYPE_OPTION = 0x04;
export const STORETYPE_DEBUG = 0x08;
export const STORETYPE_CALL = 0x10;
export const STORETYPE__MASK = 0x1F;
export interface CompilerResultExtraStore {
storeType: number; // STORETYPE__MASK
name: string; // when debug=false, the .kmx will not have store names
};
export const COMPILETARGETS_KMX = 0x01;
export const COMPILETARGETS_JS = 0x02;
export const COMPILETARGETS__MASK = 0x03;
@ -31,8 +47,13 @@ export interface CompilerResultExtra {
targets: number;
kvksFilename?: string;
displayMapFilename?: string;
stores?: CompilerResultExtraStore[];
};
//
// Internal in-memory result from a successful compilation
//
export interface CompilerResult {
kmx?: CompilerResultFile;
kvk?: CompilerResultFile;
@ -163,6 +184,24 @@ export class KmnCompiler implements UnicodeSetParser {
return 1;
}
private copyWasmResult(wasm_result: any): CompilerResult {
let result: CompilerResult = {
// We cannot Object.assign or {...} on a wasm-defined object, so...
extra: {
targets: wasm_result.extra.targets,
displayMapFilename: wasm_result.extra.displayMapFilename,
kvksFilename: wasm_result.extra.kvksFilename,
stores: []
},
displayMap: null
};
for(let store of wasm_result.extra.stores) {
result.extra.stores.push({storeType: store.storeType, name: store.name});
}
return result;
}
public runCompiler(infile: string, outfile: string, options: KmnCompilerOptions): CompilerResult {
if(!this.verifyInitialized()) {
/* c8 ignore next 2 */
@ -191,15 +230,7 @@ export class KmnCompiler implements UnicodeSetParser {
return null;
}
const result: CompilerResult = {
// We cannot Object.assign or {...} on a wasm-defined object, so...
extra: {
targets: wasm_result.extra.targets,
displayMapFilename: wasm_result.extra.displayMapFilename,
kvksFilename: wasm_result.extra.kvksFilename,
},
displayMap: null
};
const result: CompilerResult = this.copyWasmResult(wasm_result);
if(result.extra.targets & COMPILETARGETS_KMX) {
result.kmx = {
@ -234,15 +265,8 @@ export class KmnCompiler implements UnicodeSetParser {
if(!wasm_result.result) {
return null;
}
const kmw_result: CompilerResult = {
extra: {
// We cannot Object.assign or {...} on a wasm-defined object, so...
targets: wasm_result.extra.targets,
displayMapFilename: wasm_result.extra.displayMapFilename,
kvksFilename: wasm_result.extra.kvksFilename,
},
displayMap: result.displayMap // we can safely re-use the kmx compile displayMap
};
const kmw_result: CompilerResult = this.copyWasmResult(wasm_result);
kmw_result.displayMap = result.displayMap; // we can safely re-use the kmx compile displayMap
let web_kmx = new Uint8Array(Module.HEAP8.buffer, wasm_result.kmx, wasm_result.kmxSize)
result.js = this.runWebCompiler(infile, outfile, web_kmx, result.kvk?.data, kmw_result, options);

View file

@ -39,8 +39,8 @@ KMXCodeNames: string[] = [
export const
USEnglishUnshift: string = ' `' + '1234567890' + '-' + '=' + 'qwertyuiop' + '[' + ']' + '\\' + 'asdfghjkl' + ';' + '\'' + 'zxcvbnm' + ',' + '.' + '/',
USEnglishShift: string = 0xFF + '~' + '!@#$%^&*()' + '_' + '+' + 'QWERTYUIOP' + '{' + '}' + '|' + 'ASDFGHJKL' + ':' + '"' + 'ZXCVBNM' + '<' + '>' + '?',
USEnglishValues: string = 0x20 + 0xc0 + '1234567890' + 0xbd + 0xbb + 'QWERTYUIOP' + 0xdb + 0xdd + 0xdc + 'ASDFGHJKL' + 0xba + 0xde + 'ZXCVBNM' + 0xbc + 0xbe + 0xbf,
USEnglishShift: string = '\u00FF' + '~' + '!@#$%^&*()' + '_' + '+' + 'QWERTYUIOP' + '{' + '}' + '|' + 'ASDFGHJKL' + ':' + '"' + 'ZXCVBNM' + '<' + '>' + '?',
USEnglishValues: string = '\u0020' + '\u00c0' + '1234567890' + '\u00bd' + '\u00bb' + 'QWERTYUIOP' + '\u00db' + '\u00dd' + '\u00dc' + 'ASDFGHJKL' + '\u00ba' + '\u00de' + 'ZXCVBNM' + '\u00bc' + '\u00be' + '\u00bf',
UnreachableKeyCodes: number[] = [ // I4141
0x00, // &H0
0x01, //VK_LBUTTON, // &H1

View file

@ -5,7 +5,7 @@ import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaS
import { KmwCompilerMessages } from "./messages.js";
import { ValidateLayoutFile } from "./validate-layout-file.js";
import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js";
import { CompilerResult } from "src/compiler/compiler.js";
import { CompilerResult, STORETYPE_DEBUG, STORETYPE_OPTION, STORETYPE_RESERVED } from "../compiler/compiler.js";
function requote(s: string): string {
return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'";
@ -34,7 +34,14 @@ export function RequotedString(s: string, RequoteSingleQuotes: boolean = false):
return s;
}
export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: string, keyboardData: Uint8Array, kvkData: Uint8Array, kmxResult: CompilerResult, FDebug: boolean = false): string {
export function WriteCompiledKeyboard(
callbacks: CompilerCallbacks,
kmnfile: string,
keyboardData: Uint8Array,
kvkData: Uint8Array,
kmxResult: CompilerResult,
FDebug: boolean = false
): string {
let opts: CompilerOptions = {
shouldAddCompilerVersion: false,
saveDebug: FDebug
@ -217,18 +224,10 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str
result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`;
}
function isDebugStore(fsp: KMX.STORE) {
return fsp.dwSystemID == KMX.KMXFile.TSS_DEBUG_LINE;
}
function isReservedStore(fsp: KMX.STORE) {
return fsp.dwSystemID != KMX.KMXFile.TSS_NONE;
}
function isOptionStore(fsp: KMX.STORE) {
// TODO: how do we determine this, see CheckStoreUsage()
return false;
}
const isStoreType = (index:number, type: number) => !!(kmxResult.extra.stores[index].storeType & type);
const isDebugStore = (index: number) => isStoreType(index, STORETYPE_DEBUG);
const isReservedStore = (index: number) => isStoreType(index, STORETYPE_RESERVED);
const isOptionStore = (index: number) => isStoreType(index, STORETYPE_OPTION);
// Write the stores out
FOptionStores = '';
@ -236,7 +235,7 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str
let fsp = keyboard.stores[i];
// I3438 - Save all system stores to the keyboard, for now // I3684
if (!isDebugStore(fsp)) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then
if (!isDebugStore(i)) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then
if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPARISON) {
result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`;
}
@ -245,14 +244,14 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str
}
//else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary
// Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl])
else if (isOptionStore(fsp) && !isReservedStore(fsp)) {
else if (isOptionStore(i) && !isReservedStore(i)) {
result += `${FTabStop}this.s${JavaScript_Name(i,fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.dpName,true)}",`+
`${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)});${nl}`;
if (FOptionStores != '') {
FOptionStores += ',';
}
FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}`;
FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}'`;
}
else if (fsp.dwSystemID == KMX.KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) {
result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; // I3681

View file

@ -0,0 +1,17 @@
@echo off
echo Compiles the keyboards using the legacy kmcomp.exe
echo to use as baseline comparisons for kmc kmw module
rem we run for the .kmx first even though we don't use them because the legacy
rem cmdline web compiler has a bit of an issue generating the VK properly if we
rem build the .kmn directly and haven't already built the .kmx (which generates
rem the .kvk that the web compiler is expecting). This doesn't happen in project
rem mode because the .kmx is always built first. Probably won't fix this because
rem legacy compiler is being replaced anyway.
for %%d in (*.kmn) do ..\..\..\..\..\bin\kmcomp -no-compiler-version -d %%d %%~nd.kmx
for %%d in (*.kmn) do ..\..\..\..\..\bin\kmcomp -no-compiler-version -d %%d %%~nd.js
rem ok, we no longer need .kmx and .kvk once we've built the .js fixtures
del *.kmx
rem We can't do `del *.kvk` because that also deletes *.kvks, thanks 8.3
rem filenames! But the following horror works:
for %%d in (*.kvk) do if %%~xd == .kvk del %%d

View file

@ -0,0 +1,699 @@
if(typeof keyman === 'undefined') {
console.log('Keyboard requires KeymanWeb 10.0 or later');
if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");
} else {
KeymanWeb.KR(new Keyboard_test_keychars());
}
function Keyboard_test_keychars()
{
var modCodes = keyman.osk.modifierCodes;
var keyCodes = keyman.osk.keyCodes;
this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;
this.KI="Keyboard_test_keychars";
this.KN="test_keychars";
this.KMINVER="10.0";
this.KV=null;
this.KDU=0;
this.KH='';
this.KM=0;
this.KBVER="1.0";
this.KMBM=modCodes.SHIFT /* 0x0010 */;
this.s_letter_6=" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
this.KVS=[];
this.gs=function(t,e) {
return this.g_Main_0(t,e);
};
this.gs=function(t,e) {
return this.g_Main_0(t,e);
};
this.g_Main_0=function(t,e) {
var k=KeymanWeb,r=0,m=0;
if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SPACE /* 0x20 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"- -");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_1 /* 0x31 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-!-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_QUOTE /* 0xDE */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-\"-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_3 /* 0x33 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-#-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_4 /* 0x34 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-$-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_5 /* 0x35 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-%-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_7 /* 0x37 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-&-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_QUOTE /* 0xDE */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-'-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_9 /* 0x39 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-(-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_0 /* 0x30 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-)-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_8 /* 0x38 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-*-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_EQUAL /* 0xBB */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-+-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COMMA /* 0xBC */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-,-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_HYPHEN /* 0xBD */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"---");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_PERIOD /* 0xBE */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-.-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SLASH /* 0xBF */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-/-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-0-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-1-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-2-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-3-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-4-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-5-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_6 /* 0x36 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-6-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_7 /* 0x37 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-7-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_8 /* 0x38 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-8-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_9 /* 0x39 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-9-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COLON /* 0xBA */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-:-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COLON /* 0xBA */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-;-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COMMA /* 0xBC */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-<-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_EQUAL /* 0xBB */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-=-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_PERIOD /* 0xBE */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"->-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SLASH /* 0xBF */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-?-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_2 /* 0x32 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-@-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_A /* 0x41 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-A-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_B /* 0x42 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-B-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_C /* 0x43 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-C-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_D /* 0x44 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-D-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_E /* 0x45 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-E-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_F /* 0x46 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-F-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_G /* 0x47 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-G-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_H /* 0x48 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-H-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_I /* 0x49 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-I-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_J /* 0x4A */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-J-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_K /* 0x4B */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-K-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_L /* 0x4C */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-L-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_M /* 0x4D */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-M-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_N /* 0x4E */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-N-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_O /* 0x4F */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-O-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_P /* 0x50 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-P-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Q /* 0x51 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-Q-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_R /* 0x52 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-R-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_S /* 0x53 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-S-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_T /* 0x54 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-T-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_U /* 0x55 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-U-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_V /* 0x56 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-V-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_W /* 0x57 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-W-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_X /* 0x58 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-X-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Y /* 0x59 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-Y-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Z /* 0x5A */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-Z-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_LBRKT /* 0xDB */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-[-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSLASH /* 0xDC */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-\\-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_RBRKT /* 0xDD */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-]-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_6 /* 0x36 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-^-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_HYPHEN /* 0xBD */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-_-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKQUOTE /* 0xC0 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-`-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-a-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-b-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-c-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-d-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-e-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_F /* 0x46 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-f-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_G /* 0x47 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-g-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_H /* 0x48 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-h-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_I /* 0x49 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-i-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_J /* 0x4A */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-j-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_K /* 0x4B */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-k-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_L /* 0x4C */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-l-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_M /* 0x4D */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-m-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_N /* 0x4E */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-n-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_O /* 0x4F */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-o-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_P /* 0x50 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-p-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Q /* 0x51 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-q-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_R /* 0x52 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-r-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_S /* 0x53 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-s-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_T /* 0x54 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-t-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_U /* 0x55 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-u-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_V /* 0x56 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-v-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_W /* 0x57 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-w-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_X /* 0x58 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-x-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Y /* 0x59 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-y-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Z /* 0x5A */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-z-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_LBRKT /* 0xDB */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-{-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKSLASH /* 0xDC */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-|-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_RBRKT /* 0xDD */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-}-");
}
}
else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKQUOTE /* 0xC0 */)) {
if(1){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"-~-");
}
}
return r;
};
}

View file

@ -0,0 +1,14 @@
c Verifies every letter on the US English keyboard, ensuring
c that our mapping tables are correct
store(&NAME) 'test_keychars'
store(&version) '10.0'
store(&targets) 'any'
begin Unicode > use(Main)
group(Main) using keys
store(letter) ' !"#$%&' "'" '()*+,-./' '0'..'9' ':;<=>?@' 'A'..'Z' '[\]^_`' 'a'..'z' '{|}~'
+ any(letter) > '-' index(letter, 1) '-'

View file

@ -0,0 +1,64 @@
if(typeof keyman === 'undefined') {
console.log('Keyboard requires KeymanWeb 10.0 or later');
if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");
} else {
KeymanWeb.KR(new Keyboard_test_options());
}
function Keyboard_test_options()
{
var modCodes = keyman.osk.modifierCodes;
var keyCodes = keyman.osk.keyCodes;
this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;
this.KI="Keyboard_test_options";
this.KN="test_options";
this.KMINVER="10.0";
this.KV=null;
this.KDU=0;
this.KH='';
this.KM=0;
this.KBVER="1.0";
this.KMBM=0 /* 0x0000 */;
this.s_foo_5=KeymanWeb.KLOAD(this.KI,"foo","0");
this.s8="1";
this.s9="0";
this.s10="1";
this.s11="0";
this.KVS=['s_foo_5'];
this.gs=function(t,e) {
return this.g_Main_0(t,e);
};
this.gs=function(t,e) {
return this.g_Main_0(t,e);
};
this.g_Main_0=function(t,e) {
var k=KeymanWeb,r=0,m=0;
if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) {
if(1){
r=m=1; // Line 16
k.KDC(0,t);
this.s_foo_5=this.s11;
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) {
if(1){
r=m=1; // Line 15
k.KDC(0,t);
this.s_foo_5=this.s10;
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) {
if(this.s_foo_5===this.s8){
r=m=1; // Line 13
k.KDC(0,t);
k.KO(-1,t,"foo.");
}
else if(this.s_foo_5===this.s9){
r=m=1; // Line 14
k.KDC(0,t);
k.KO(-1,t,"no foo.");
}
}
return r;
};
}

View file

@ -0,0 +1,16 @@
c Adapted from common baseline test keyboard k_021__options.kmn
store(&NAME) 'test_options'
store(&version) '10.0'
store(&targets) 'any'
store(foo) '0'
begin Unicode > use(Main)
group(Main) using keys
if(foo = '1') + 'a' > 'foo.'
if(foo = '0') + 'a' > 'no foo.'
+ '1' > set(foo = '1')
+ '0' > set(foo = '0')

View file

@ -1,50 +0,0 @@
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { KmnCompiler } from '../../src/compiler/compiler.js';
import { extractTouchLayout } from './util.js';
const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/');
const fixturesDir = __dirname + '/../../../test/fixtures/kmw/';
const fixtureName = fixturesDir + 'khmer_angkor.js';
const infile = fixturesDir + 'khmer_angkor.kmn';
const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile
const testOutfile = fixturesDir + 'khmer_angkor.test.js';
if(fs.existsSync(testOutfile)) {
fs.unlinkSync(testOutfile);
}
const callbacks = new TestCompilerCallbacks();
const kmnCompiler = new KmnCompiler();
if(!await kmnCompiler.init(callbacks)) {
console.error('kmx compiler failed to init');
process.exit(1);
}
let result = kmnCompiler.runCompiler(infile, outfile, {
shouldAddCompilerVersion: false,
saveDebug: true, // TODO: we should probably use passed debug flag
});
if(!result) {
callbacks.printMessages();
process.exit(1);
}
const js = new TextDecoder().decode(result.js.data);
callbacks.printMessages();
const fjs = fs.readFileSync(fixtureName, 'utf8');
const expected = extractTouchLayout(fjs);
const actual = extractTouchLayout(js);
if(expected.js !== actual.js) {
fs.writeFileSync(testOutfile, js);
console.error('JS not equal');
process.exit(1);
}

View file

@ -1,60 +0,0 @@
import 'mocha';
import { assert } from 'chai';
// import sinonChai from 'sinon-chai';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { KmnCompiler } from '../../src/compiler/compiler.js';
import { extractTouchLayout } from './util.js';
const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/');
const fixturesDir = __dirname + '/../../../test/fixtures/kmw/';
//const baselineDir = __dirname + '/../../../../../common/test/keyboards/baseline/';
// chai.use(sinonChai);
describe('Compiler class', function() {
const callbacks = new TestCompilerCallbacks();
this.afterEach(function() {
callbacks.printMessages();
callbacks.clear();
});
it('should compile a basic keyboard', async function() {
// const compiler = new KeymanWebCompiler(callbacks, {addCompilerVersion: false, debug: true});
const fixtureName = fixturesDir + 'khmer_angkor.js';
const infile = fixturesDir + 'khmer_angkor.kmn';
const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile
const testOutfile = fixturesDir + 'khmer_angkor.test.js';
if(fs.existsSync(testOutfile)) {
fs.unlinkSync(testOutfile);
}
const kmnCompiler = new KmnCompiler();
assert.isTrue(await kmnCompiler.init(callbacks));
let result = kmnCompiler.runCompiler(infile, outfile, {
shouldAddCompilerVersion: false,
saveDebug: true, // TODO: we should probably use passed debug flag
});
assert.isNotNull(result);
const js = new TextDecoder().decode(result.js.data);
const fjs = fs.readFileSync(fixtureName, 'utf8');
const expected = extractTouchLayout(fjs);
const actual = extractTouchLayout(js);
fs.writeFileSync(testOutfile + '.strip.js', actual.js);
fs.writeFileSync(fixtureName + '.strip.js', expected.js);
fs.writeFileSync(testOutfile, js);
assert.deepEqual(actual.js, expected.js);
assert.deepEqual(JSON.parse(actual.touchLayout), JSON.parse(expected.touchLayout));
});
});

View file

@ -0,0 +1,92 @@
import 'mocha';
import { assert } from 'chai';
// import sinonChai from 'sinon-chai';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { CompilerResult, KmnCompiler } from '../../src/compiler/compiler.js';
import { ETLResult, extractTouchLayout as parseWebTestResult } from './util.js';
import { KeymanFileTypes } from '@keymanapp/common-types';
const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/');
const fixturesDir = __dirname + '/../../../test/fixtures/kmw/';
//const baselineDir = __dirname + '/../../../../../common/test/keyboards/baseline/';
// chai.use(sinonChai);
const debug=false;
const generateTestFilenames = (id: string) => ({
fixture: fixturesDir + id + KeymanFileTypes.Binary.WebKeyboard,
source: fixturesDir + id + KeymanFileTypes.Source.KeymanKeyboard,
intermediate: fixturesDir + id + KeymanFileTypes.Binary.Keyboard,
binary: fixturesDir + id + '.test' + KeymanFileTypes.Binary.WebKeyboard
});
describe('KeymanWeb Compiler', function() {
const callbacks = new TestCompilerCallbacks();
const kmnCompiler: KmnCompiler = new KmnCompiler();
this.beforeAll(async function() {
assert.isTrue(await kmnCompiler.init(callbacks));
});
this.afterEach(function() {
callbacks.printMessages();
callbacks.clear();
});
it('should compile a complex keyboard', async function() {
run_test_keyboard(kmnCompiler, 'khmer_angkor');
});
it('should handle option stores', async function() {
//
// This is enough to verify that the option store is set appropriately with
// KLOAD because the fixture has that code present:
//
// this.s_foo_6=KeymanWeb.KLOAD(this.KI,"foo","0");
//
run_test_keyboard(kmnCompiler, 'test_options');
});
it('should translate every "character style" key correctly', async function() {
//
// This is enough to verify that every character style key is encoded in the
// same way as the fixture.
//
run_test_keyboard(kmnCompiler, 'test_keychars');
});
});
function run_test_keyboard(kmnCompiler: KmnCompiler, id: string): { result: CompilerResult, actualCode: string, actual: ETLResult, expectedCode: string, expected: ETLResult } {
const filenames = generateTestFilenames(id);
let result = kmnCompiler.runCompiler(filenames.source, filenames.intermediate, {
shouldAddCompilerVersion: false,
saveDebug: true,
});
assert.isNotNull(result);
let value = {
result,
actualCode: new TextDecoder().decode(result.js.data),
expectedCode: fs.readFileSync(filenames.fixture, 'utf8'),
expected: <ETLResult>null,
actual: <ETLResult>null,
};
value.actual = parseWebTestResult(value.actualCode);
value.expected = parseWebTestResult(value.expectedCode);
assert.deepEqual(value.actual.js, value.expected.js);
assert.deepEqual(JSON.parse(value.actual.touchLayout), JSON.parse(value.expected.touchLayout));
if(debug) {
// This is mostly to allow us to verify that parseWebTestResult is doing what we want
fs.writeFileSync(filenames.binary + '.strip.js', value.actual.js);
fs.writeFileSync(filenames.fixture + '.strip.js', value.expected.js);
fs.writeFileSync(filenames.binary, value.actualCode);
}
return value;
}

View file

@ -1,5 +1,5 @@
interface ETLResult {
export interface ETLResult {
js: string;
touchLayout: string;
}
@ -7,7 +7,10 @@ interface ETLResult {
export function extractTouchLayout(js: string): ETLResult|null {
let m = /KVKL=(?<kvkl>.+?);[\r\n]/ds.exec(js);
if(!m) {
return null;
return {
js: js,
touchLayout: 'null'
};
}
let kvkl = (<any>m).indices.groups.kvkl;

View file

@ -1,6 +1,7 @@
#pragma once
#include <fstream>
#include <vector>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
@ -30,6 +31,22 @@ struct KMCMP_COMPILER_OPTIONS {
int target; // CKF_KEYMAN, CKF_KEYMANWEB
};
//
// Additional metadata passed sideband from compiler result
//
#define STORETYPE_STORE 0x01
#define STORETYPE_RESERVED 0x02
#define STORETYPE_OPTION 0x04
#define STORETYPE_DEBUG 0x08
#define STORETYPE_CALL 0x10
#define STORETYPE__MASK 0x1F
struct KMCMP_COMPILER_RESULT_EXTRA_STORE {
int storeType; // STORETYPE__MASK
std::string name; // when debug=false, the .kmx will not have store names
};
#define COMPILETARGETS_KMX 0x01
#define COMPILETARGETS_JS 0x02
#define COMPILETARGETS__MASK 0x03
@ -39,6 +56,7 @@ struct KMCMP_COMPILER_RESULT_EXTRA {
std::string kmnFilename;
std::string kvksFilename;
std::string displayMapFilename;
std::vector<KMCMP_COMPILER_RESULT_EXTRA_STORE> stores;
};
struct KMCMP_COMPILER_RESULT {

View file

@ -7,6 +7,10 @@
#include "CompileKeyboardBuffer.h"
#include "../../../../common/windows/cpp/include/keymanversion.h"
namespace kmcmp {
void CopyExtraData(PFILE_KEYBOARD fk);
};
bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
{
PKMX_WCHAR str, p;
@ -45,6 +49,7 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
fk->extra->targets = COMPILETARGETS_KMX;
fk->extra->kvksFilename = "";
fk->extra->displayMapFilename = "";
fk->extra->stores.clear();
/* fk->szMessage[0] = 0;
fk->szLanguageName[0] = 0;*/
fk->dwBitmapSize = 0;
@ -158,5 +163,26 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
/* Flag presence of deprecated features */
kmcmp::CheckForDeprecatedFeatures(fk);
/* Extract extra metadata for callers */
kmcmp::CopyExtraData(fk);
return TRUE;
}
namespace kmcmp {
void CopyExtraData(PFILE_KEYBOARD fk) {
/* Copy stores */
PFILE_STORE store = fk->dpStoreArray;
for(int i = 0; i < fk->cxStoreArray; i++, store++) {
KMCMP_COMPILER_RESULT_EXTRA_STORE extraStore;
extraStore.storeType =
(store->fIsStore ? STORETYPE_STORE : 0) |
(store->fIsReserved ? STORETYPE_RESERVED : 0) |
(store->fIsOption ? STORETYPE_OPTION : 0) |
(store->fIsDebug ? STORETYPE_DEBUG : 0) |
(store->fIsCall ? STORETYPE_CALL : 0);
extraStore.name = string_from_u16string(store->szName);
fk->extra->stores.push_back(extraStore);
}
}
}

View file

@ -79,6 +79,38 @@ WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPI
return r;
}
// This little bit of magic gives us implicit bindings for any `std::vector`,
// so long as we bind `emscripten::value_object<T>`, and comes from:
// https://github.com/emscripten-core/emscripten/issues/11070#issuecomment-717675128
namespace emscripten {
namespace internal {
template <typename T, typename Allocator>
struct BindingType<std::vector<T, Allocator>> {
using ValBinding = BindingType<val>;
using WireType = ValBinding::WireType;
static WireType toWireType(const std::vector<T, Allocator> &vec) {
return ValBinding::toWireType(val::array(vec));
}
static std::vector<T, Allocator> fromWireType(WireType value) {
return vecFromJSArray<T>(ValBinding::fromWireType(value));
}
};
template <typename T>
struct TypeID<T,
typename std::enable_if_t<std::is_same<
typename Canonicalized<T>::type,
std::vector<typename Canonicalized<T>::type::value_type,
typename Canonicalized<T>::type::allocator_type>>::value>> {
static constexpr TYPEID get() { return TypeID<val>::get(); }
};
} // namespace internal
} // namespace emscripten
EMSCRIPTEN_BINDINGS(compiler_interface) {
emscripten::class_<KMCMP_COMPILER_OPTIONS>("CompilerOptions")
@ -109,6 +141,12 @@ EMSCRIPTEN_BINDINGS(compiler_interface) {
.property("kmnFilename", &KMCMP_COMPILER_RESULT_EXTRA::kmnFilename)
.property("kvksFilename", &KMCMP_COMPILER_RESULT_EXTRA::kvksFilename)
.property("displayMapFilename", &KMCMP_COMPILER_RESULT_EXTRA::displayMapFilename)
.property("stores", &KMCMP_COMPILER_RESULT_EXTRA::stores)
;
emscripten::value_object<KMCMP_COMPILER_RESULT_EXTRA_STORE>("CompilerResultExtraStore")
.field("storeType", &KMCMP_COMPILER_RESULT_EXTRA_STORE::storeType)
.field("name", &KMCMP_COMPILER_RESULT_EXTRA_STORE::name)
;
emscripten::function("kmcmp_compile", &kmcmp_wasm_compile);