mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-19 12:27:47 +00:00
Merge pull request #8276 from keymanapp/feat/core/8069-key2-keys-epic-ldml
feat(core): ldml rename key2 to keys 🙀
This commit is contained in:
commit
bc68033183
20 changed files with 335 additions and 353 deletions
|
|
@ -1,18 +1,18 @@
|
|||
|
||||
import { constants } from "@keymanapp/ldml-keyboard-constants";
|
||||
import { Key2Flick, KMXPlusData, StrsItem } from "../kmx-plus.js";
|
||||
import { KeysFlick, KMXPlusData, StrsItem } from "../kmx-plus.js";
|
||||
import { build_strs_index, BUILDER_STRS } from "./build-strs.js";
|
||||
import { build_list_index, BUILDER_LIST } from "./build-list.js";
|
||||
import { BUILDER_SECTION } from "./builder-section.js";
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* key2 section
|
||||
* keys section
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* This struct is a single <key> in the key2 keybag
|
||||
* This struct is a single <key> in the keys keybag
|
||||
*/
|
||||
interface BUILDER_KEY2_KEY {
|
||||
interface BUILDER_KEYS_KEY {
|
||||
to: number; // str or single codepoint
|
||||
flags: number;
|
||||
id: number; // str with original key id
|
||||
|
|
@ -28,59 +28,59 @@ interface BUILDER_KEY2_KEY {
|
|||
/**
|
||||
* This is a <flicks>, a list of <flick> elements.
|
||||
*/
|
||||
interface BUILDER_KEY2_FLICKS {
|
||||
count: number; // number of BUILDER_KEY2_FLICK entries in this flick list
|
||||
interface BUILDER_KEYS_FLICKS {
|
||||
count: number; // number of BUILDER_KEYS_FLICK entries in this flick list
|
||||
flick: number; // index into the flick[] subtable of the first flick in the list
|
||||
id: number; // str with the original id of this flicks
|
||||
_id: string; // copy of the flicks id, used for sorting during build
|
||||
_flicks: Key2Flick[]; // temporary copy of Key2Flick object
|
||||
_flicks: KeysFlick[]; // temporary copy of KeysFlick object
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a single <flick> element.
|
||||
*/
|
||||
interface BUILDER_KEY2_FLICK {
|
||||
interface BUILDER_KEYS_FLICK {
|
||||
directions: number; // list of cardinal/intercardinal directions
|
||||
flags: number; //
|
||||
to: number; // str or single codepoint
|
||||
};
|
||||
|
||||
|
||||
interface BUILDER_KEY2_KMAP {
|
||||
interface BUILDER_KEYS_KMAP {
|
||||
vkey: number;
|
||||
mod: number;
|
||||
key: number; //index to key2.key
|
||||
key: number; //index to keys.key
|
||||
};
|
||||
|
||||
/**
|
||||
* Builder for the 'keys' section
|
||||
*/
|
||||
export interface BUILDER_KEY2 extends BUILDER_SECTION {
|
||||
export interface BUILDER_KEYS extends BUILDER_SECTION {
|
||||
ident: number;
|
||||
size: number;
|
||||
keyCount: number;
|
||||
flicksCount: number;
|
||||
flickCount: number;
|
||||
kmapCount: number;
|
||||
keys: BUILDER_KEY2_KEY[];
|
||||
flicks: BUILDER_KEY2_FLICKS[];
|
||||
flick: BUILDER_KEY2_FLICK[];
|
||||
kmap: BUILDER_KEY2_KMAP[];
|
||||
keys: BUILDER_KEYS_KEY[];
|
||||
flicks: BUILDER_KEYS_FLICKS[];
|
||||
flick: BUILDER_KEYS_FLICK[];
|
||||
kmap: BUILDER_KEYS_KMAP[];
|
||||
};
|
||||
|
||||
export function build_key2(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_list: BUILDER_LIST): BUILDER_KEY2 {
|
||||
if(kmxplus.key2.keys.length == 0 &&
|
||||
(kmxplus.key2.flicks.length <= 1)) { // if no keys and only the 'null' flick.
|
||||
export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_list: BUILDER_LIST): BUILDER_KEYS {
|
||||
if(kmxplus.keys.keys.length == 0 &&
|
||||
(kmxplus.keys.flicks.length <= 1)) { // if no keys and only the 'null' flick.
|
||||
return null;
|
||||
}
|
||||
|
||||
let key2: BUILDER_KEY2 = {
|
||||
ident: constants.hex_section_id(constants.section.key2),
|
||||
let keys: BUILDER_KEYS = {
|
||||
ident: constants.hex_section_id(constants.section.keys),
|
||||
size: 0,
|
||||
keyCount: kmxplus.key2.keys.length,
|
||||
flicksCount: kmxplus.key2.flicks.length,
|
||||
keyCount: kmxplus.keys.keys.length,
|
||||
flicksCount: kmxplus.keys.flicks.length,
|
||||
flickCount: 0,
|
||||
kmapCount: kmxplus.key2.kmap.length,
|
||||
kmapCount: kmxplus.keys.kmap.length,
|
||||
keys: [],
|
||||
flicks: [],
|
||||
flick: [],
|
||||
|
|
@ -90,11 +90,11 @@ export function build_key2(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
|
|||
|
||||
// flicks first: the keys will need to index into the flicks table.
|
||||
|
||||
// Note that per the Key2 class and spec, there is always a flicks=0 meaning 'no flicks'
|
||||
key2.flicks = kmxplus.key2.flicks.map((flicks) => {
|
||||
let result : BUILDER_KEY2_FLICKS = {
|
||||
// Note that per the Keys class and spec, there is always a flicks=0 meaning 'no flicks'
|
||||
keys.flicks = kmxplus.keys.flicks.map((flicks) => {
|
||||
let result : BUILDER_KEYS_FLICKS = {
|
||||
count: flicks.flicks.length,
|
||||
flick: key2.flick.length, // index of first flick
|
||||
flick: keys.flick.length, // index of first flick
|
||||
id: build_strs_index(sect_strs, flicks.id),
|
||||
_id: flicks.id.value,
|
||||
_flicks: flicks.flicks,
|
||||
|
|
@ -102,22 +102,22 @@ export function build_key2(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
|
|||
return result;
|
||||
});
|
||||
// Sort the flicks array by id
|
||||
key2.flicks.sort((a, b) => StrsItem.binaryStringCompare(a._id, b._id));
|
||||
keys.flicks.sort((a, b) => StrsItem.binaryStringCompare(a._id, b._id));
|
||||
// now, allocate 'flick' entries for each 'flicks'
|
||||
key2.flicks.forEach((flicks) => {
|
||||
keys.flicks.forEach((flicks) => {
|
||||
flicks._flicks.forEach((flick) => {
|
||||
key2.flick.push({
|
||||
keys.flick.push({
|
||||
directions: build_list_index(sect_list, flick.directions),
|
||||
flags: flick.flags,
|
||||
to: build_strs_index(sect_strs, flick.to),
|
||||
});
|
||||
key2.flickCount++;
|
||||
keys.flickCount++;
|
||||
});
|
||||
});
|
||||
|
||||
// now, keys
|
||||
key2.keys = kmxplus.key2.keys.map((key) => {
|
||||
let result : BUILDER_KEY2_KEY = {
|
||||
keys.keys = kmxplus.keys.keys.map((key) => {
|
||||
let result : BUILDER_KEYS_KEY = {
|
||||
to: build_strs_index(sect_strs, key.to),
|
||||
flags: key.flags,
|
||||
id: build_strs_index(sect_strs, key.id),
|
||||
|
|
@ -127,33 +127,33 @@ export function build_key2(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
|
|||
longPress: build_list_index(sect_list, key.longPress),
|
||||
longPressDefault: build_strs_index(sect_strs, key.longPressDefault),
|
||||
multiTap: build_list_index(sect_list, key.multiTap),
|
||||
flicks: key2.flicks.findIndex(v => v._id === (key.flicks || '')), // flicks id='' is the 'null' flicks
|
||||
flicks: keys.flicks.findIndex(v => v._id === (key.flicks || '')), // flicks id='' is the 'null' flicks
|
||||
};
|
||||
// Make sure the flicks were found
|
||||
if (result.flicks === -1) {
|
||||
throw new Error(`Key2: Could not find flicks id=${key.flicks} for key=${key.id.value}`);
|
||||
throw new Error(`Keys: Could not find flicks id=${key.flicks} for key=${key.id.value}`);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
// sort the keys by id
|
||||
key2.keys.sort((a, b) => StrsItem.binaryStringCompare(a._id, b._id));
|
||||
keys.keys.sort((a, b) => StrsItem.binaryStringCompare(a._id, b._id));
|
||||
|
||||
// finally, kmap
|
||||
key2.kmap = kmxplus.key2.kmap.map(({vkey, mod, key}) => {
|
||||
let result : BUILDER_KEY2_KMAP = {
|
||||
keys.kmap = kmxplus.keys.kmap.map(({vkey, mod, key}) => {
|
||||
let result : BUILDER_KEYS_KMAP = {
|
||||
vkey,
|
||||
mod,
|
||||
key: key2.keys.findIndex(k => k._id === key),
|
||||
key: keys.keys.findIndex(k => k._id === key),
|
||||
};
|
||||
// Make sure the key was found
|
||||
if (result.key === -1) {
|
||||
throw new Error(`Key2: Could not find key2.key id=${result.key} for key2.kmap.key=${key}`);
|
||||
throw new Error(`Keys: Could not find keys.key id=${result.key} for keys.kmap.key=${key}`);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
// Sort kmap by vkey, mod order, per C7043
|
||||
key2.kmap.sort((a,b) => {
|
||||
keys.kmap.sort((a,b) => {
|
||||
let rc = 0;
|
||||
if (rc === 0) {
|
||||
rc = (a.vkey - b.vkey);
|
||||
|
|
@ -164,12 +164,12 @@ export function build_key2(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
|
|||
return rc;
|
||||
});
|
||||
|
||||
let offset = constants.length_key2 +
|
||||
(constants.length_key2_key * key2.keyCount) +
|
||||
(constants.length_key2_flick_element * key2.flickCount) +
|
||||
(constants.length_key2_flick_list * key2.flicksCount) +
|
||||
(constants.length_key2_kmap * key2.kmapCount);
|
||||
key2.size = offset;
|
||||
let offset = constants.length_keys +
|
||||
(constants.length_keys_key * keys.keyCount) +
|
||||
(constants.length_keys_flick_element * keys.flickCount) +
|
||||
(constants.length_keys_flick_list * keys.flicksCount) +
|
||||
(constants.length_keys_kmap * keys.kmapCount);
|
||||
keys.size = offset;
|
||||
|
||||
return key2;
|
||||
return keys;
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import { BUILDER_SECTION } from './builder-section.js';
|
|||
import { BUILDER_SECT, build_sect } from './build-sect.js';
|
||||
import { BUILDER_DISP, build_disp } from './build-disp.js';
|
||||
import { BUILDER_ELEM, build_elem } from './build-elem.js';
|
||||
import { BUILDER_KEY2, build_key2 } from './build-key2.js';
|
||||
import { BUILDER_KEYS, build_keys } from './build-keys.js';
|
||||
import { BUILDER_LAYR, build_layr } from './build-layr.js';
|
||||
import { BUILDER_LIST, build_list } from './build-list.js';
|
||||
import { BUILDER_LOCA, build_loca } from './build-loca.js';
|
||||
|
|
@ -26,7 +26,7 @@ type SectionBuilders = {
|
|||
disp?: BUILDER_DISP;
|
||||
elem?: BUILDER_ELEM;
|
||||
finl?: BUILDER_FINL;
|
||||
key2?: BUILDER_KEY2;
|
||||
keys?: BUILDER_KEYS;
|
||||
layr?: BUILDER_LAYR;
|
||||
list?: BUILDER_LIST;
|
||||
loca?: BUILDER_LOCA;
|
||||
|
|
@ -62,7 +62,7 @@ export default class KMXPlusBuilder {
|
|||
this.emitSection(file, this.file.COMP_PLUS_ELEM, this.sect.elem);
|
||||
this.emitElements(file);
|
||||
this.emitSection(file, this.file.COMP_PLUS_FINL, this.sect.finl);
|
||||
this.emitSection(file, this.file.COMP_PLUS_KEY2, this.sect.key2);
|
||||
this.emitSection(file, this.file.COMP_PLUS_KEYS, this.sect.keys);
|
||||
this.emitSection(file, this.file.COMP_PLUS_LAYR, this.sect.layr);
|
||||
this.emitSection(file, this.file.COMP_PLUS_LIST, this.sect.list);
|
||||
this.emitSection(file, this.file.COMP_PLUS_LOCA, this.sect.loca);
|
||||
|
|
@ -92,7 +92,7 @@ export default class KMXPlusBuilder {
|
|||
this.sect.bksp = build_bksp(this.file.kmxplus.bksp, this.sect.strs, this.sect.elem);
|
||||
this.sect.disp = build_disp(this.file.kmxplus, this.sect.strs);
|
||||
this.sect.finl = build_finl(this.file.kmxplus.finl, this.sect.strs, this.sect.elem);
|
||||
this.sect.key2 = build_key2(this.file.kmxplus, this.sect.strs, this.sect.list);
|
||||
this.sect.keys = build_keys(this.file.kmxplus, this.sect.strs, this.sect.list);
|
||||
this.sect.layr = build_layr(this.file.kmxplus, this.sect.strs, this.sect.list);
|
||||
this.sect.loca = build_loca(this.file.kmxplus, this.sect.strs);
|
||||
this.sect.meta = build_meta(this.file.kmxplus, this.sect.strs);
|
||||
|
|
@ -128,7 +128,7 @@ export default class KMXPlusBuilder {
|
|||
offset = this.finalize_sect_item(this.sect.disp, offset);
|
||||
offset = this.finalize_sect_item(this.sect.elem, offset);
|
||||
offset = this.finalize_sect_item(this.sect.finl, offset);
|
||||
offset = this.finalize_sect_item(this.sect.key2, offset);
|
||||
offset = this.finalize_sect_item(this.sect.keys, offset);
|
||||
offset = this.finalize_sect_item(this.sect.layr, offset);
|
||||
offset = this.finalize_sect_item(this.sect.list, offset);
|
||||
offset = this.finalize_sect_item(this.sect.loca, offset);
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ export class Layr extends Section {
|
|||
lists: LayrList[] = [];
|
||||
};
|
||||
|
||||
export class Key2Keys {
|
||||
export class KeysKeys {
|
||||
flags: number;
|
||||
flicks: string; // for in-memory only
|
||||
id: StrsItem;
|
||||
|
|
@ -258,16 +258,16 @@ export class Key2Keys {
|
|||
};
|
||||
|
||||
|
||||
export class Key2Kmap {
|
||||
export class KeysKmap {
|
||||
vkey: number;
|
||||
mod: number;
|
||||
key: string; // for in-memory only
|
||||
};
|
||||
|
||||
export class Key2Flicks {
|
||||
flicks: Key2Flick[] = [];
|
||||
export class KeysFlicks {
|
||||
flicks: KeysFlick[] = [];
|
||||
id: StrsItem;
|
||||
compareTo(b: Key2Flicks): number {
|
||||
compareTo(b: KeysFlicks): number {
|
||||
return this.id.compareTo(b.id);
|
||||
}
|
||||
constructor(id: StrsItem) {
|
||||
|
|
@ -275,19 +275,19 @@ export class Key2Flicks {
|
|||
}
|
||||
};
|
||||
|
||||
export class Key2Flick {
|
||||
export class KeysFlick {
|
||||
directions: ListItem;
|
||||
flags: number;
|
||||
to: StrsItem;
|
||||
};
|
||||
|
||||
export class Key2 extends Section {
|
||||
keys: Key2Keys[] = [];
|
||||
flicks: Key2Flicks[] = [];
|
||||
kmap: Key2Kmap[] = [];
|
||||
export class Keys extends Section {
|
||||
keys: KeysKeys[] = [];
|
||||
flicks: KeysFlicks[] = [];
|
||||
kmap: KeysKmap[] = [];
|
||||
constructor(strs: Strs) {
|
||||
super();
|
||||
let nullFlicks = new Key2Flicks(strs.allocString(''));
|
||||
let nullFlicks = new KeysFlicks(strs.allocString(''));
|
||||
this.flicks.push(nullFlicks); // C7043: null element string
|
||||
}
|
||||
};
|
||||
|
|
@ -347,7 +347,7 @@ export interface KMXPlusData {
|
|||
disp?: Disp;
|
||||
elem?: Elem; // elem is ignored in-memory
|
||||
finl?: Finl;
|
||||
key2?: Key2;
|
||||
keys?: Keys;
|
||||
layr?: Layr;
|
||||
list?: List; // list is ignored in-memory
|
||||
loca?: Loca;
|
||||
|
|
@ -381,7 +381,7 @@ export class KMXPlusFile extends KMXFile {
|
|||
public readonly COMP_PLUS_FINL_ITEM: any;
|
||||
public readonly COMP_PLUS_FINL: any;
|
||||
|
||||
// COMP_PLUS_KEYS is now COMP_PLUS_KEY2_KMAP
|
||||
// COMP_PLUS_KEYS is now COMP_PLUS_KEYS_KMAP
|
||||
|
||||
public readonly COMP_PLUS_LAYR_ENTRY: any;
|
||||
public readonly COMP_PLUS_LAYR_KEY: any;
|
||||
|
|
@ -389,11 +389,11 @@ export class KMXPlusFile extends KMXFile {
|
|||
public readonly COMP_PLUS_LAYR_ROW: any;
|
||||
public readonly COMP_PLUS_LAYR: any;
|
||||
|
||||
public readonly COMP_PLUS_KEY2_FLICK: any;
|
||||
public readonly COMP_PLUS_KEY2_FLICKS: any;
|
||||
public readonly COMP_PLUS_KEY2_KEY: any;
|
||||
public readonly COMP_PLUS_KEY2_KMAP: any;
|
||||
public readonly COMP_PLUS_KEY2: any;
|
||||
public readonly COMP_PLUS_KEYS_FLICK: any;
|
||||
public readonly COMP_PLUS_KEYS_FLICKS: any;
|
||||
public readonly COMP_PLUS_KEYS_KEY: any;
|
||||
public readonly COMP_PLUS_KEYS_KMAP: any;
|
||||
public readonly COMP_PLUS_KEYS: any;
|
||||
|
||||
public readonly COMP_PLUS_LIST_LIST: any;
|
||||
public readonly COMP_PLUS_LIST_INDEX: any;
|
||||
|
|
@ -482,7 +482,7 @@ export class KMXPlusFile extends KMXFile {
|
|||
|
||||
// 'finl' - see 'tran'
|
||||
|
||||
// 'keys' - see 'key2.kmap'
|
||||
// 'keys' - see 'keys.kmap'
|
||||
|
||||
// 'layr'
|
||||
|
||||
|
|
@ -522,19 +522,19 @@ export class KMXPlusFile extends KMXFile {
|
|||
keys: new r.Array(this.COMP_PLUS_LAYR_KEY, 'keyCount'),
|
||||
});
|
||||
|
||||
this.COMP_PLUS_KEY2_FLICK = new r.Struct({
|
||||
this.COMP_PLUS_KEYS_FLICK = new r.Struct({
|
||||
directions: r.uint32le, // list
|
||||
flags: r.uint32le,
|
||||
to: r.uint32le, // str | codepoint
|
||||
});
|
||||
|
||||
this.COMP_PLUS_KEY2_FLICKS = new r.Struct({
|
||||
this.COMP_PLUS_KEYS_FLICKS = new r.Struct({
|
||||
count: r.uint32le,
|
||||
flick: r.uint32le,
|
||||
id: r.uint32le, // str
|
||||
});
|
||||
|
||||
this.COMP_PLUS_KEY2_KEY = new r.Struct({
|
||||
this.COMP_PLUS_KEYS_KEY = new r.Struct({
|
||||
to: r.uint32le, // str | codepoint
|
||||
flags: r.uint32le,
|
||||
id: r.uint32le, // str
|
||||
|
|
@ -546,23 +546,23 @@ export class KMXPlusFile extends KMXFile {
|
|||
flicks: r.uint32le, // index into flicks table
|
||||
});
|
||||
|
||||
this.COMP_PLUS_KEY2_KMAP = new r.Struct({
|
||||
this.COMP_PLUS_KEYS_KMAP = new r.Struct({
|
||||
vkey: r.uint32le,
|
||||
mod: r.uint32le,
|
||||
key: r.uint32le, // index into 'keys' subtable
|
||||
});
|
||||
|
||||
this.COMP_PLUS_KEY2 = new r.Struct({
|
||||
this.COMP_PLUS_KEYS = new r.Struct({
|
||||
ident: r.uint32le,
|
||||
size: r.uint32le,
|
||||
keyCount: r.uint32le,
|
||||
flicksCount: r.uint32le,
|
||||
flickCount: r.uint32le,
|
||||
kmapCount: r.uint32le,
|
||||
keys: new r.Array(this.COMP_PLUS_KEY2_KEY, 'keyCount'),
|
||||
flicks: new r.Array(this.COMP_PLUS_KEY2_FLICKS, 'flicksCount'),
|
||||
flick: new r.Array(this.COMP_PLUS_KEY2_FLICK, 'flickCount'),
|
||||
kmap: new r.Array(this.COMP_PLUS_KEY2_KMAP, 'kmapCount'),
|
||||
keys: new r.Array(this.COMP_PLUS_KEYS_KEY, 'keyCount'),
|
||||
flicks: new r.Array(this.COMP_PLUS_KEYS_FLICKS, 'flicksCount'),
|
||||
flick: new r.Array(this.COMP_PLUS_KEYS_FLICK, 'flickCount'),
|
||||
kmap: new r.Array(this.COMP_PLUS_KEYS_KMAP, 'kmapCount'),
|
||||
});
|
||||
|
||||
// 'list'
|
||||
|
|
|
|||
|
|
@ -174,25 +174,21 @@ export function testTestdataReaderCases(cases : TestDataCase[]) {
|
|||
assert.notOk(source, `loading ${testcase.subpath} (expected failure)`);
|
||||
}
|
||||
// special case for an expected exception
|
||||
if (testcase.throws) {
|
||||
assert.throws(() => reader.validate(source, loadLdmlKeyboardTestDataSchema()), testcase.throws);
|
||||
} else {
|
||||
assert.doesNotThrow(() => reader.validate(source, loadLdmlKeyboardTestDataSchema()), `validating ${testcase.subpath}`);
|
||||
// if we expected errors or warnings, show them
|
||||
if (testcase.errors) {
|
||||
assert.includeDeepMembers(callbacks.messages, testcase.errors, 'expected errors to be included');
|
||||
}
|
||||
if (testcase.warnings) {
|
||||
assert.includeDeepMembers(callbacks.messages, testcase.warnings, 'expected warnings to be included');
|
||||
} else if (!expectFailure) {
|
||||
// no warnings, so expect zero messages
|
||||
assert.strictEqual(callbacks.messages.length, 0, 'expected zero messages but got ' +callbacks.messages.map(e => e.message).join(' ') );
|
||||
}
|
||||
// TODO-LDML: no validation for now.
|
||||
// if we expected errors or warnings, show them
|
||||
if (testcase.errors) {
|
||||
assert.includeDeepMembers(callbacks.messages, testcase.errors, 'expected errors to be included');
|
||||
}
|
||||
if (testcase.warnings) {
|
||||
assert.includeDeepMembers(callbacks.messages, testcase.warnings, 'expected warnings to be included');
|
||||
} else if (!expectFailure) {
|
||||
// no warnings, so expect zero messages
|
||||
assert.strictEqual(callbacks.messages.length, 0, 'expected zero messages but got ' +callbacks.messages.map(e => e.message).join(' ') );
|
||||
}
|
||||
|
||||
// run the user-supplied callback if any
|
||||
if (testcase.callback) {
|
||||
testcase.callback(data, source, testcase.subpath, callbacks);
|
||||
}
|
||||
// run the user-supplied callback if any
|
||||
if (testcase.callback) {
|
||||
testcase.callback(data, source, testcase.subpath, callbacks);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
#define LDML_ELEM_FLAGS_TERTIARY_MASK 0xFF000000
|
||||
#define LDML_ELEM_FLAGS_UNICODE_SET 0x1
|
||||
#define LDML_FINL_FLAGS_ERROR 0x1
|
||||
#define LDML_KEY2_FLICK_FLAGS_EXTEND 0x1
|
||||
#define LDML_KEY2_KEY_FLAGS_EXTEND 0x1
|
||||
#define LDML_KEY2_KEY_FLAGS_GAP 0x2
|
||||
#define LDML_KEY2_KEY_FLAGS_NOTRANSFORM 0x4
|
||||
#define LDML_KEYS_FLICK_FLAGS_EXTEND 0x1
|
||||
#define LDML_KEYS_KEY_FLAGS_EXTEND 0x1
|
||||
#define LDML_KEYS_KEY_FLAGS_GAP 0x2
|
||||
#define LDML_KEYS_KEY_FLAGS_NOTRANSFORM 0x4
|
||||
#define LDML_KEYS_MOD_ALL 0x11F
|
||||
#define LDML_KEYS_MOD_ALT 0xC
|
||||
#define LDML_KEYS_MOD_ALTL 0x4
|
||||
|
|
@ -57,11 +57,11 @@
|
|||
#define LDML_LENGTH_FINL 0x8
|
||||
#define LDML_LENGTH_FINL_ITEM 0x10
|
||||
#define LDML_LENGTH_HEADER 0x8
|
||||
#define LDML_LENGTH_KEY2 0x18
|
||||
#define LDML_LENGTH_KEY2_FLICK_ELEMENT 0xC
|
||||
#define LDML_LENGTH_KEY2_FLICK_LIST 0xC
|
||||
#define LDML_LENGTH_KEY2_KEY 0x24
|
||||
#define LDML_LENGTH_KEY2_KMAP 0xC
|
||||
#define LDML_LENGTH_KEYS 0x18
|
||||
#define LDML_LENGTH_KEYS_FLICK_ELEMENT 0xC
|
||||
#define LDML_LENGTH_KEYS_FLICK_LIST 0xC
|
||||
#define LDML_LENGTH_KEYS_KEY 0x24
|
||||
#define LDML_LENGTH_KEYS_KMAP 0xC
|
||||
#define LDML_LENGTH_LAYR 0x18
|
||||
#define LDML_LENGTH_LAYR_ENTRY 0x10
|
||||
#define LDML_LENGTH_LAYR_KEY 0x4
|
||||
|
|
@ -96,8 +96,8 @@
|
|||
#define LDML_SECTIONNAME_ELEM "elem"
|
||||
#define LDML_SECTIONID_FINL 0x6C6E6966 /* "finl" */
|
||||
#define LDML_SECTIONNAME_FINL "finl"
|
||||
#define LDML_SECTIONID_KEY2 0x3279656B /* "key2" */
|
||||
#define LDML_SECTIONNAME_KEY2 "key2"
|
||||
#define LDML_SECTIONID_KEYS 0x7379656B /* "keys" */
|
||||
#define LDML_SECTIONNAME_KEYS "keys"
|
||||
#define LDML_SECTIONID_LAYR 0x7279616C /* "layr" */
|
||||
#define LDML_SECTIONNAME_LAYR "layr"
|
||||
#define LDML_SECTIONID_LIST 0x7473696C /* "list" */
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export type SectionIdent =
|
|||
'disp' |
|
||||
'elem' |
|
||||
'finl' |
|
||||
'key2' |
|
||||
'keys' |
|
||||
'layr' |
|
||||
'list' |
|
||||
'loca' |
|
||||
|
|
@ -224,7 +224,7 @@ class Constants {
|
|||
readonly finl_flags_error = 0x0001;
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* keys section is now key2.kmap
|
||||
* keys section is now keys.kmap
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
|
|
@ -287,49 +287,49 @@ class Constants {
|
|||
readonly keys_mod_all: number = Array.from(this.keys_mod_map.values()).reduce((p, v) => (p | v), this.keys_mod_none);
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* key2 section
|
||||
* keys section
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Minimum length of the 'key2' section not including variable parts
|
||||
* Minimum length of the 'keys' section not including variable parts
|
||||
*/
|
||||
readonly length_key2 = 24;
|
||||
readonly length_keys = 24;
|
||||
/**
|
||||
* Length of each item in the 'key2' keys sub-table
|
||||
* Length of each item in the 'keys' keys sub-table
|
||||
*/
|
||||
readonly length_key2_key = 36;
|
||||
readonly length_keys_key = 36;
|
||||
/**
|
||||
* Length of each item in the 'key2' flick lists sub-table
|
||||
* Length of each item in the 'keys' flick lists sub-table
|
||||
*/
|
||||
readonly length_key2_flick_list = 12;
|
||||
readonly length_keys_flick_list = 12;
|
||||
/**
|
||||
* Length of each item in the 'key2' flick elements sub-table
|
||||
* Length of each item in the 'keys' flick elements sub-table
|
||||
*/
|
||||
readonly length_key2_flick_element = 12;
|
||||
readonly length_keys_flick_element = 12;
|
||||
/**
|
||||
* Length of each item in the 'key2.kmap' key map subtable
|
||||
* Length of each item in the 'keys.kmap' key map subtable
|
||||
*/
|
||||
readonly length_key2_kmap = 12;
|
||||
readonly length_keys_kmap = 12;
|
||||
|
||||
/**
|
||||
* 0 if to is a char, 1 if it is a string
|
||||
*/
|
||||
readonly key2_key_flags_extend = 0x00000001;
|
||||
readonly keys_key_flags_extend = 0x00000001;
|
||||
|
||||
/**
|
||||
* 1 if the key is a gap
|
||||
*/
|
||||
readonly key2_key_flags_gap = 0x00000002;
|
||||
readonly keys_key_flags_gap = 0x00000002;
|
||||
|
||||
/**
|
||||
* 1 if the key is transform=no
|
||||
*/
|
||||
readonly key2_key_flags_notransform = 0x00000004;
|
||||
readonly keys_key_flags_notransform = 0x00000004;
|
||||
|
||||
/**
|
||||
* 0 if to is a char, 1 if it is a string
|
||||
*/
|
||||
readonly key2_flick_flags_extend = 0x00000001;
|
||||
readonly keys_flick_flags_extend = 0x00000001;
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* layr section
|
||||
|
|
@ -517,7 +517,7 @@ class Constants {
|
|||
disp: 'disp',
|
||||
elem: 'elem',
|
||||
finl: 'finl',
|
||||
key2: 'key2',
|
||||
keys: 'keys',
|
||||
layr: 'layr',
|
||||
list: 'list',
|
||||
loca: 'loca',
|
||||
|
|
|
|||
|
|
@ -538,63 +538,63 @@ COMP_KMXPLUS_LAYR_Helper::getKey(KMX_DWORD key) const {
|
|||
}
|
||||
|
||||
bool
|
||||
COMP_KMXPLUS_KEY2::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
COMP_KMXPLUS_KEYS::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
if (header.size < sizeof(*this)
|
||||
+ (keyCount * sizeof(COMP_KMXPLUS_KEY2_KEY))
|
||||
+ (flicksCount * sizeof(COMP_KMXPLUS_KEY2_FLICK_LIST))
|
||||
+ (flickCount * sizeof(COMP_KMXPLUS_KEY2_FLICK_ELEMENT))
|
||||
+ (kmapCount * sizeof(COMP_KMXPLUS_KEY2_KMAP))) {
|
||||
+ (keyCount * sizeof(COMP_KMXPLUS_KEYS_KEY))
|
||||
+ (flicksCount * sizeof(COMP_KMXPLUS_KEYS_FLICK_LIST))
|
||||
+ (flickCount * sizeof(COMP_KMXPLUS_KEYS_FLICK_ELEMENT))
|
||||
+ (kmapCount * sizeof(COMP_KMXPLUS_KEYS_KMAP))) {
|
||||
DebugLog("header.size < expected size");
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
// further validation in the COMP_KMXPLUS_KEY2_Helper helper obj
|
||||
// further validation in the COMP_KMXPLUS_KEYS_Helper helper obj
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
COMP_KMXPLUS_KEY2_Helper::COMP_KMXPLUS_KEY2_Helper() : key2(nullptr), is_valid(false) {
|
||||
COMP_KMXPLUS_KEYS_Helper::COMP_KMXPLUS_KEYS_Helper() : key2(nullptr), is_valid(false) {
|
||||
}
|
||||
|
||||
bool
|
||||
COMP_KMXPLUS_KEY2_Helper::setKey2(const COMP_KMXPLUS_KEY2 *newKey2) {
|
||||
DebugLog("validating newKey2=%p", newKey2);
|
||||
COMP_KMXPLUS_KEYS_Helper::setKeys(const COMP_KMXPLUS_KEYS *newKeys) {
|
||||
DebugLog("validating newKeys=%p", newKeys);
|
||||
is_valid = true;
|
||||
if (newKey2 == nullptr) {
|
||||
if (newKeys == nullptr) {
|
||||
// null = invalid
|
||||
is_valid = false;
|
||||
// No assert here: just a missing layer
|
||||
return false;
|
||||
}
|
||||
key2 = newKey2;
|
||||
const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(newKey2);
|
||||
rawdata += LDML_LENGTH_KEY2; // skip past non-dynamic portion
|
||||
key2 = newKeys;
|
||||
const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(newKeys);
|
||||
rawdata += LDML_LENGTH_KEYS; // skip past non-dynamic portion
|
||||
// keys
|
||||
if (key2->keyCount > 0) {
|
||||
keys = reinterpret_cast<const COMP_KMXPLUS_KEY2_KEY *>(rawdata);
|
||||
keys = reinterpret_cast<const COMP_KMXPLUS_KEYS_KEY *>(rawdata);
|
||||
} else {
|
||||
keys = nullptr;
|
||||
is_valid = false;
|
||||
assert(is_valid);
|
||||
}
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEY2_KEY) * key2->keyCount;
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEYS_KEY) * key2->keyCount;
|
||||
// flicks
|
||||
if (key2->flicksCount > 0) {
|
||||
flickLists = reinterpret_cast<const COMP_KMXPLUS_KEY2_FLICK_LIST *>(rawdata);
|
||||
flickLists = reinterpret_cast<const COMP_KMXPLUS_KEYS_FLICK_LIST *>(rawdata);
|
||||
} else {
|
||||
flickLists = nullptr; // not an error
|
||||
}
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEY2_FLICK_LIST) * key2->flicksCount;
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEYS_FLICK_LIST) * key2->flicksCount;
|
||||
// flick
|
||||
if (key2->flickCount > 0) {
|
||||
flickElements = reinterpret_cast<const COMP_KMXPLUS_KEY2_FLICK_ELEMENT *>(rawdata);
|
||||
flickElements = reinterpret_cast<const COMP_KMXPLUS_KEYS_FLICK_ELEMENT *>(rawdata);
|
||||
} else {
|
||||
flickElements = nullptr; // not an error
|
||||
}
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEY2_FLICK_ELEMENT) * key2->flickCount;
|
||||
rawdata += sizeof(COMP_KMXPLUS_KEYS_FLICK_ELEMENT) * key2->flickCount;
|
||||
// kmap
|
||||
if (key2->kmapCount > 0) {
|
||||
kmap = reinterpret_cast<const COMP_KMXPLUS_KEY2_KMAP *>(rawdata);
|
||||
kmap = reinterpret_cast<const COMP_KMXPLUS_KEYS_KMAP *>(rawdata);
|
||||
} else {
|
||||
kmap = nullptr; // not an error
|
||||
}
|
||||
|
|
@ -654,13 +654,13 @@ COMP_KMXPLUS_KEY2_Helper::setKey2(const COMP_KMXPLUS_KEY2 *newKey2) {
|
|||
}
|
||||
}
|
||||
// Return results
|
||||
DebugLog("COMP_KMXPLUS_KEY2_Helper.setKey2(): %s", is_valid ? "valid" : "invalid");
|
||||
DebugLog("COMP_KMXPLUS_KEYS_Helper.setKeys(): %s", is_valid ? "valid" : "invalid");
|
||||
assert(is_valid);
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
const COMP_KMXPLUS_KEY2_KEY *
|
||||
COMP_KMXPLUS_KEY2_Helper::getKeys(KMX_DWORD i) const {
|
||||
const COMP_KMXPLUS_KEYS_KEY *
|
||||
COMP_KMXPLUS_KEYS_Helper::getKeys(KMX_DWORD i) const {
|
||||
if (!valid() || i >= key2->keyCount) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
|
|
@ -668,8 +668,8 @@ COMP_KMXPLUS_KEY2_Helper::getKeys(KMX_DWORD i) const {
|
|||
return keys + i;
|
||||
}
|
||||
|
||||
const COMP_KMXPLUS_KEY2_KEY*
|
||||
COMP_KMXPLUS_KEY2_Helper::findKeyByStringId(KMX_DWORD strId, KMX_DWORD &i) const {
|
||||
const COMP_KMXPLUS_KEYS_KEY*
|
||||
COMP_KMXPLUS_KEYS_Helper::findKeyByStringId(KMX_DWORD strId, KMX_DWORD &i) const {
|
||||
for (i = 0; i < key2->keyCount; i++) {
|
||||
if (keys[i].id == strId) {
|
||||
return &keys[i];
|
||||
|
|
@ -678,8 +678,8 @@ COMP_KMXPLUS_KEY2_Helper::findKeyByStringId(KMX_DWORD strId, KMX_DWORD &i) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const COMP_KMXPLUS_KEY2_FLICK_LIST *
|
||||
COMP_KMXPLUS_KEY2_Helper::getFlickLists(KMX_DWORD i) const {
|
||||
const COMP_KMXPLUS_KEYS_FLICK_LIST *
|
||||
COMP_KMXPLUS_KEYS_Helper::getFlickLists(KMX_DWORD i) const {
|
||||
if (!valid() || i >= key2->flicksCount) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
|
|
@ -687,8 +687,8 @@ COMP_KMXPLUS_KEY2_Helper::getFlickLists(KMX_DWORD i) const {
|
|||
return flickLists + i;
|
||||
}
|
||||
|
||||
const COMP_KMXPLUS_KEY2_FLICK_ELEMENT *
|
||||
COMP_KMXPLUS_KEY2_Helper::getFlickElements(KMX_DWORD i) const {
|
||||
const COMP_KMXPLUS_KEYS_FLICK_ELEMENT *
|
||||
COMP_KMXPLUS_KEYS_Helper::getFlickElements(KMX_DWORD i) const {
|
||||
if (!valid() || i >= key2->flickCount) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
|
|
@ -696,8 +696,8 @@ COMP_KMXPLUS_KEY2_Helper::getFlickElements(KMX_DWORD i) const {
|
|||
return flickElements + i;
|
||||
}
|
||||
|
||||
const COMP_KMXPLUS_KEY2_KMAP *
|
||||
COMP_KMXPLUS_KEY2_Helper::getKmap(KMX_DWORD i) const {
|
||||
const COMP_KMXPLUS_KEYS_KMAP *
|
||||
COMP_KMXPLUS_KEYS_Helper::getKmap(KMX_DWORD i) const {
|
||||
if (!valid() || i >= key2->kmapCount) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
|
|
@ -706,8 +706,8 @@ COMP_KMXPLUS_KEY2_Helper::getKmap(KMX_DWORD i) const {
|
|||
}
|
||||
|
||||
std::u16string
|
||||
COMP_KMXPLUS_KEY2_KEY::get_string() const {
|
||||
assert(!(flags & LDML_KEY2_KEY_FLAGS_EXTEND)); // should not be called.
|
||||
COMP_KMXPLUS_KEYS_KEY::get_string() const {
|
||||
assert(!(flags & LDML_KEYS_KEY_FLAGS_EXTEND)); // should not be called.
|
||||
char16_single buf;
|
||||
const int len = Utf32CharToUtf16(to, buf);
|
||||
return std::u16string(buf.ch, len);
|
||||
|
|
@ -849,7 +849,7 @@ kmx_plus::kmx_plus(const COMP_KEYBOARD *keyboard, size_t length)
|
|||
// these will be nullptr if they don't validate
|
||||
disp = section_from_sect<COMP_KMXPLUS_DISP>(sect);
|
||||
elem = section_from_sect<COMP_KMXPLUS_ELEM>(sect);
|
||||
key2 = section_from_sect<COMP_KMXPLUS_KEY2>(sect);
|
||||
key2 = section_from_sect<COMP_KMXPLUS_KEYS>(sect);
|
||||
layr = section_from_sect<COMP_KMXPLUS_LAYR>(sect);
|
||||
list = section_from_sect<COMP_KMXPLUS_LIST>(sect);
|
||||
loca = section_from_sect<COMP_KMXPLUS_LOCA>(sect);
|
||||
|
|
@ -859,7 +859,7 @@ kmx_plus::kmx_plus(const COMP_KEYBOARD *keyboard, size_t length)
|
|||
vkey = section_from_sect<COMP_KMXPLUS_VKEY>(sect);
|
||||
|
||||
// calculate and validate the dynamic parts
|
||||
(void)key2Helper.setKey2(key2);
|
||||
(void)key2Helper.setKeys(key2);
|
||||
(void)layrHelper.setLayr(layr);
|
||||
(void)listHelper.setList(list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -438,8 +438,8 @@ static_assert(sizeof(struct COMP_KMXPLUS_LAYR) == LDML_LENGTH_LAYR, "mismatched
|
|||
/* ------------------------------------------------------------------
|
||||
* key2 section
|
||||
------------------------------------------------------------------ */
|
||||
struct COMP_KMXPLUS_KEY2 {
|
||||
static const KMX_DWORD IDENT = LDML_SECTIONID_KEY2;
|
||||
struct COMP_KMXPLUS_KEYS {
|
||||
static const KMX_DWORD IDENT = LDML_SECTIONID_KEYS;
|
||||
COMP_KMXPLUS_HEADER header;
|
||||
KMX_DWORD keyCount;
|
||||
KMX_DWORD flicksCount;
|
||||
|
|
@ -456,19 +456,19 @@ struct COMP_KMXPLUS_KEY2 {
|
|||
bool valid(KMX_DWORD length) const;
|
||||
};
|
||||
|
||||
struct COMP_KMXPLUS_KEY2_FLICK_ELEMENT {
|
||||
struct COMP_KMXPLUS_KEYS_FLICK_ELEMENT {
|
||||
KMXPLUS_LIST directions;
|
||||
KMX_DWORD flags;
|
||||
KMXPLUS_STR to; // string or codepoint
|
||||
};
|
||||
|
||||
struct COMP_KMXPLUS_KEY2_FLICK_LIST {
|
||||
struct COMP_KMXPLUS_KEYS_FLICK_LIST {
|
||||
KMX_DWORD count;
|
||||
KMX_DWORD flick; // flick index
|
||||
KMXPLUS_STR id;
|
||||
};
|
||||
|
||||
struct COMP_KMXPLUS_KEY2_KEY {
|
||||
struct COMP_KMXPLUS_KEYS_KEY {
|
||||
KMXPLUS_STR to;
|
||||
KMX_DWORD flags;
|
||||
KMXPLUS_STR id;
|
||||
|
|
@ -482,26 +482,26 @@ struct COMP_KMXPLUS_KEY2_KEY {
|
|||
std::u16string get_string() const;
|
||||
};
|
||||
|
||||
struct COMP_KMXPLUS_KEY2_KMAP {
|
||||
struct COMP_KMXPLUS_KEYS_KMAP {
|
||||
KMX_DWORD vkey;
|
||||
KMX_DWORD mod;
|
||||
KMX_DWORD key; // index into key subtable
|
||||
};
|
||||
|
||||
class COMP_KMXPLUS_KEY2_Helper {
|
||||
class COMP_KMXPLUS_KEYS_Helper {
|
||||
public:
|
||||
COMP_KMXPLUS_KEY2_Helper();
|
||||
COMP_KMXPLUS_KEYS_Helper();
|
||||
/**
|
||||
* Initialize the helper to point at a layr section.
|
||||
* @return true if valid
|
||||
*/
|
||||
bool setKey2(const COMP_KMXPLUS_KEY2 *newKey2);
|
||||
bool setKeys(const COMP_KMXPLUS_KEYS *newKeys);
|
||||
inline bool valid() const { return is_valid; }
|
||||
|
||||
const COMP_KMXPLUS_KEY2_KEY *getKeys(KMX_DWORD key) const;
|
||||
const COMP_KMXPLUS_KEY2_FLICK_LIST *getFlickLists(KMX_DWORD list) const;
|
||||
const COMP_KMXPLUS_KEY2_FLICK_ELEMENT *getFlickElements(KMX_DWORD element) const;
|
||||
const COMP_KMXPLUS_KEY2_KMAP *getKmap(KMX_DWORD element) const;
|
||||
const COMP_KMXPLUS_KEYS_KEY *getKeys(KMX_DWORD key) const;
|
||||
const COMP_KMXPLUS_KEYS_FLICK_LIST *getFlickLists(KMX_DWORD list) const;
|
||||
const COMP_KMXPLUS_KEYS_FLICK_ELEMENT *getFlickElements(KMX_DWORD element) const;
|
||||
const COMP_KMXPLUS_KEYS_KMAP *getKmap(KMX_DWORD element) const;
|
||||
|
||||
/**
|
||||
* Search for a key by string id.
|
||||
|
|
@ -509,23 +509,23 @@ public:
|
|||
* @param index on exit, index of item if found. Undefined otherwise.
|
||||
* @return pointer to key or nullptr
|
||||
*/
|
||||
const COMP_KMXPLUS_KEY2_KEY *findKeyByStringId(KMX_DWORD strId, KMX_DWORD &index) const;
|
||||
const COMP_KMXPLUS_KEYS_KEY *findKeyByStringId(KMX_DWORD strId, KMX_DWORD &index) const;
|
||||
|
||||
private:
|
||||
const COMP_KMXPLUS_KEY2 *key2;
|
||||
const COMP_KMXPLUS_KEYS *key2;
|
||||
bool is_valid;
|
||||
const COMP_KMXPLUS_KEY2_KEY *keys;
|
||||
const COMP_KMXPLUS_KEY2_FLICK_LIST *flickLists;
|
||||
const COMP_KMXPLUS_KEY2_FLICK_ELEMENT *flickElements;
|
||||
const COMP_KMXPLUS_KEY2_KMAP *kmap;
|
||||
const COMP_KMXPLUS_KEYS_KEY *keys;
|
||||
const COMP_KMXPLUS_KEYS_FLICK_LIST *flickLists;
|
||||
const COMP_KMXPLUS_KEYS_FLICK_ELEMENT *flickElements;
|
||||
const COMP_KMXPLUS_KEYS_KMAP *kmap;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2_KEY) == LDML_LENGTH_KEY2_KEY, "mismatched size of key2.key");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2_FLICK_ELEMENT) == LDML_LENGTH_KEY2_FLICK_ELEMENT, "mismatched size of key2.flick");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2_FLICK_LIST) == LDML_LENGTH_KEY2_FLICK_LIST, "mismatched size of key2.flicks");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2_KMAP) == LDML_LENGTH_KEY2_KMAP, "mismatched size of key2.kmap");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2) % 0x4 == 0, "Structs prior to variable part should align to 32-bit boundary");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEY2) == LDML_LENGTH_KEY2, "mismatched size of section key2");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS_KEY) == LDML_LENGTH_KEYS_KEY, "mismatched size of key2.key");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS_FLICK_ELEMENT) == LDML_LENGTH_KEYS_FLICK_ELEMENT, "mismatched size of key2.flick");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS_FLICK_LIST) == LDML_LENGTH_KEYS_FLICK_LIST, "mismatched size of key2.flicks");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS_KMAP) == LDML_LENGTH_KEYS_KMAP, "mismatched size of key2.kmap");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS) % 0x4 == 0, "Structs prior to variable part should align to 32-bit boundary");
|
||||
static_assert(sizeof(struct COMP_KMXPLUS_KEYS) == LDML_LENGTH_KEYS, "mismatched size of section key2");
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* list section
|
||||
|
|
@ -602,7 +602,7 @@ class kmx_plus {
|
|||
// keep the next elements sorted
|
||||
const COMP_KMXPLUS_DISP *disp;
|
||||
const COMP_KMXPLUS_ELEM *elem;
|
||||
const COMP_KMXPLUS_KEY2 *key2;
|
||||
const COMP_KMXPLUS_KEYS *key2;
|
||||
const COMP_KMXPLUS_LAYR *layr;
|
||||
const COMP_KMXPLUS_LIST *list;
|
||||
const COMP_KMXPLUS_LOCA *loca;
|
||||
|
|
@ -614,7 +614,7 @@ class kmx_plus {
|
|||
inline bool is_valid() { return valid; }
|
||||
COMP_KMXPLUS_LAYR_Helper layrHelper;
|
||||
COMP_KMXPLUS_LIST_Helper listHelper;
|
||||
COMP_KMXPLUS_KEY2_Helper key2Helper;
|
||||
COMP_KMXPLUS_KEYS_Helper key2Helper;
|
||||
private:
|
||||
bool valid; // true if valid
|
||||
};
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ See [C7043.2.11](#c7043211-tran-finl-and-bksptransforms).
|
|||
|
||||
### C7043.2.5 Removed: `keys`
|
||||
|
||||
_this section has been merged into `key2.kmap`_
|
||||
_this section has been merged into the new `keys.kmap`_
|
||||
|
||||
### C7043.2.6 `loca`—Locales
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ ldml_processor::ldml_processor(path const & kb_path, const std::vector<uint8_t>
|
|||
auto keyEntry = kplus.key2Helper.getKeys(kmapEntry->key);
|
||||
assert(keyEntry != nullptr);
|
||||
|
||||
if (keyEntry->flags && LDML_KEY2_KEY_FLAGS_EXTEND) {
|
||||
if (keyEntry->flags && LDML_KEYS_KEY_FLAGS_EXTEND) {
|
||||
if (nullptr == kplus.strs) {
|
||||
DebugLog("for keys: kplus.strs == nullptr"); // need a string table to get strings
|
||||
assert(false);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using namespace km::kbp::kmx;
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
COMP_KMXPLUS_KEY2_KEY e[2] = {
|
||||
COMP_KMXPLUS_KEYS_KEY e[2] = {
|
||||
{
|
||||
0x00000127, // to = U+0127 = 295
|
||||
0x00000000 // flags: !EXTEND
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import CompilerOptions from './compiler-options.js';
|
|||
import { CompilerMessages } from './messages.js';
|
||||
import { BkspCompiler, FinlCompiler, TranCompiler } from './tran.js';
|
||||
import { DispCompiler } from './disp.js';
|
||||
import { Key2Compiler } from './key2.js';
|
||||
import { KeysCompiler } from './keys.js';
|
||||
import { LayrCompiler } from './layr.js';
|
||||
import { LocaCompiler } from './loca.js';
|
||||
import { MetaCompiler } from './meta.js';
|
||||
|
|
@ -18,7 +18,7 @@ const SECTION_COMPILERS = [
|
|||
BkspCompiler,
|
||||
DispCompiler,
|
||||
FinlCompiler,
|
||||
Key2Compiler,
|
||||
KeysCompiler,
|
||||
LayrCompiler,
|
||||
LocaCompiler,
|
||||
MetaCompiler,
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ import { CompilerMessages } from './messages.js';
|
|||
import { SectionCompiler } from "./section-compiler.js";
|
||||
|
||||
import GlobalSections = KMXPlus.GlobalSections;
|
||||
import Key2 = KMXPlus.Key2;
|
||||
import Keys = KMXPlus.Keys;
|
||||
import ListItem = KMXPlus.ListItem;
|
||||
import Key2Flicks = KMXPlus.Key2Flicks;
|
||||
import KeysFlicks = KMXPlus.KeysFlicks;
|
||||
import { allUsedKeyIdsInLayers, calculateUniqueKeys, translateLayerAttrToModifier, validModifier } from '../util/util.js';
|
||||
|
||||
export class Key2Compiler extends SectionCompiler {
|
||||
export class KeysCompiler extends SectionCompiler {
|
||||
|
||||
public get id() {
|
||||
return constants.section.key2;
|
||||
return constants.section.keys;
|
||||
}
|
||||
|
||||
public validate() {
|
||||
|
|
@ -36,13 +36,13 @@ export class Key2Compiler extends SectionCompiler {
|
|||
return valid;
|
||||
}
|
||||
|
||||
public compile(sections: GlobalSections): Key2 {
|
||||
public compile(sections: GlobalSections): Keys {
|
||||
if (!this.keyboard?.keys?.key && !this.keyboard?.keys?.flicks) {
|
||||
// short-circuit if no keys or flicks
|
||||
return null;
|
||||
}
|
||||
|
||||
let sect = new Key2(sections.strs);
|
||||
let sect = new Keys(sections.strs);
|
||||
|
||||
// Load the flicks first
|
||||
this.loadFlicks(sections, sect);
|
||||
|
|
@ -65,15 +65,15 @@ export class Key2Compiler extends SectionCompiler {
|
|||
return sect;
|
||||
}
|
||||
|
||||
public loadFlicks(sections: GlobalSections, sect: Key2) {
|
||||
public loadFlicks(sections: GlobalSections, sect: Keys) {
|
||||
for (let lkflicks of this.keyboard.keys.flicks) {
|
||||
let flicks: Key2Flicks = new Key2Flicks(sections.strs.allocString(lkflicks.id));
|
||||
let flicks: KeysFlicks = new KeysFlicks(sections.strs.allocString(lkflicks.id));
|
||||
|
||||
for (let lkflick of lkflicks.flick) {
|
||||
let flags = 0;
|
||||
// TODO-LDML: single char
|
||||
const to = sections.strs.allocAndUnescapeString(lkflick.to);
|
||||
flags |= constants.key2_flick_flags_extend;
|
||||
flags |= constants.keys_flick_flags_extend;
|
||||
let directions : ListItem = sections.list.allocListFromSpaces(sections.strs, lkflick.directions);
|
||||
flicks.flicks.push({
|
||||
directions,
|
||||
|
|
@ -86,7 +86,7 @@ export class Key2Compiler extends SectionCompiler {
|
|||
}
|
||||
}
|
||||
|
||||
public loadKeys(sections: GlobalSections, sect: Key2) {
|
||||
public loadKeys(sections: GlobalSections, sect: Keys) {
|
||||
const usedKeys = allUsedKeyIdsInLayers(this.keyboard?.layers);
|
||||
const uniqueKeys = calculateUniqueKeys([...this.keyboard.keys?.key]);
|
||||
|
||||
|
|
@ -99,17 +99,17 @@ export class Key2Compiler extends SectionCompiler {
|
|||
const flicks = key.flicks;
|
||||
// TODO-LDML: verify that this flick id exists
|
||||
if (!!key.gap) {
|
||||
flags |= constants.key2_key_flags_gap;
|
||||
flags |= constants.keys_key_flags_gap;
|
||||
}
|
||||
if (key.transform === 'no') {
|
||||
flags |= constants.key2_key_flags_notransform;
|
||||
flags |= constants.keys_key_flags_notransform;
|
||||
}
|
||||
const id = sections.strs.allocString(key.id);
|
||||
const longPress: ListItem = sections.list.allocListFromEscapedSpaces(sections.strs, key.longPress);
|
||||
const longPressDefault = sections.strs.allocAndUnescapeString(key.longPressDefault);
|
||||
const multiTap: ListItem = sections.list.allocListFromEscapedSpaces(sections.strs, key.multiTap);
|
||||
const keySwitch = sections.strs.allocString(key.switch); // 'switch' is a reserved word
|
||||
flags |= constants.key2_key_flags_extend;
|
||||
flags |= constants.keys_key_flags_extend;
|
||||
const to = sections.strs.allocAndUnescapeString(key.to); // TODO-LDML: single char
|
||||
const width = Math.ceil((key.width || 1) * 10.0); // default, width=1
|
||||
sect.keys.push({
|
||||
|
|
@ -188,9 +188,9 @@ export class Key2Compiler extends SectionCompiler {
|
|||
private compileHardwareLayerToKmap(
|
||||
sections: GlobalSections,
|
||||
layer: LDMLKeyboard.LKLayer,
|
||||
sect: Key2,
|
||||
sect: Keys,
|
||||
hardware: string,
|
||||
): Key2 {
|
||||
): Keys {
|
||||
const mod = translateLayerAttrToModifier(layer);
|
||||
const keymap = Constants.HardwareToKeymap.get(hardware);
|
||||
|
||||
|
|
@ -107,8 +107,8 @@ block(sectitems)
|
|||
66 69 6e 6c
|
||||
diff(sect,finl)
|
||||
|
||||
6b 65 79 32
|
||||
diff(sect,key2)
|
||||
6b 65 79 73
|
||||
diff(sect,keys)
|
||||
|
||||
6c 61 79 72
|
||||
diff(sect,layr)
|
||||
|
|
@ -255,12 +255,12 @@ block(finl)
|
|||
01 00 00 00 # KMX_DWORD flags;
|
||||
# };
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
# key2
|
||||
# keys
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
|
||||
block(key2) # struct COMP_KMXPLUS_KEY2 {
|
||||
6b 65 79 32 # KMX_DWORD header.ident; // 0000 Section name - key2
|
||||
sizeof(key2) # KMX_DWORD header.size; // 0004 Section length
|
||||
block(keys) # struct COMP_KMXPLUS_KEYS {
|
||||
6b 65 79 73 # KMX_DWORD header.ident; // 0000 Section name - keys
|
||||
sizeof(keys) # KMX_DWORD header.size; // 0004 Section length
|
||||
02 00 00 00 # KMX_DWORD keyCount
|
||||
01 00 00 00 # KMX_DWORD flicksCount
|
||||
00 00 00 00 # KMX_DWORD flickCount
|
||||
|
|
@ -277,7 +277,7 @@ block(key2) # struct COMP_KMXPLUS_KEY2 {
|
|||
00 00 00 00 # TODO: index(listNull,listNull,4) # LIST multiTap
|
||||
00 00 00 00 # flicks 0
|
||||
# (#0001) that
|
||||
index(strNull,strKey2,2) # KMXPLUS_STR 'U+0127'
|
||||
index(strNull,strKeys,2) # KMXPLUS_STR 'U+0127'
|
||||
01 00 00 00 # KMX_DWORD flags = extend
|
||||
index(strNull,strThat,2) # KMXPLUS_STR 'hmaqtugha'
|
||||
00 00 00 00 # KMXPLUS_STR switch
|
||||
|
|
@ -301,9 +301,6 @@ block(key2) # struct COMP_KMXPLUS_KEY2 {
|
|||
31 00 00 00 00 00 00 00 01 00 00 00 # KMX_DWORD vkey, mod, key;
|
||||
c0 00 00 00 00 00 00 00 00 00 00 00 # KMX_DWORD vkey, mod, key;
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
# keys is now under key2.kmap
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
# layr
|
||||
|
|
@ -442,7 +439,7 @@ block(strs) # struct COMP_KMXPLUS_STRS {
|
|||
diff(strs,strThat) sizeof(strThat,2)
|
||||
diff(strs,strTranTo) sizeof(strTranTo,2)
|
||||
diff(strs,strKey1) sizeof(strKey1,2)
|
||||
diff(strs,strKey2) sizeof(strKey2,2)
|
||||
diff(strs,strKeys) sizeof(strKeys,2)
|
||||
diff(strs,strElemOrdrFrom3) sizeof(strElemOrdrFrom3,2)
|
||||
diff(strs,strElemOrdrFrom1) sizeof(strElemOrdrFrom1,2)
|
||||
diff(strs,strElemOrdrBefore) sizeof(strElemOrdrBefore,2)
|
||||
|
|
@ -470,7 +467,7 @@ block(strs) # struct COMP_KMXPLUS_STRS {
|
|||
block(strThat) 74 00 68 00 61 00 74 00 block(x) 00 00 # 'that'
|
||||
block(strTranTo) E2 00 block(x) 00 00 # 'â'
|
||||
block(strKey1) 27 01 block(x) 00 00 # 'ħ'
|
||||
block(strKey2) 90 17 b6 17 block(x) 00 00 # 'ថា'
|
||||
block(strKeys) 90 17 b6 17 block(x) 00 00 # 'ថា'
|
||||
# <reorder before="ᩫ" from="᩠᩵ᩅ" order="10 55 10" />
|
||||
block(strElemOrdrFrom3) 45 1a block(x) 00 00 # 'ᩅ'
|
||||
block(strElemOrdrFrom1) 60 1a block(x) 00 00 # '᩠'
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<!DOCTYPE keyboard SYSTEM "../../../../../../../resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard.dtd">
|
||||
<keyboard locale="mt" conformsTo="techpreview">
|
||||
<names>
|
||||
<name value="key2-escaped2" />
|
||||
<name value="keys-escaped2" />
|
||||
</names>
|
||||
|
||||
<keys>
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { Key2Compiler } from '../src/compiler/key2.js';
|
||||
import { compilerTestCallbacks, loadSectionFixture, testCompilationCases } from './helpers/index.js';
|
||||
import { KMXPlus } from '@keymanapp/common-types';
|
||||
import { constants } from '@keymanapp/ldml-keyboard-constants';
|
||||
|
||||
import Key2 = KMXPlus.Key2;
|
||||
|
||||
describe('key2', function () {
|
||||
this.slow(500); // 0.5 sec -- json schema validation takes a while
|
||||
|
||||
it('should compile minimal keys data', function () {
|
||||
let key2 = loadSectionFixture(Key2Compiler, 'sections/keys/minimal.xml', compilerTestCallbacks) as Key2;
|
||||
assert.ok(key2);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(key2.keys.length, 1);
|
||||
assert.equal(key2.flicks.length, 1); // there's always a 'null' flick
|
||||
assert.equal(key2.keys[0].to.value, '🪦');
|
||||
assert.equal(key2.keys[0].id.value, 'grave');
|
||||
});
|
||||
|
||||
it('should compile maximal key2 data', function () {
|
||||
let key2 = loadSectionFixture(Key2Compiler, 'sections/key2/maximal.xml', compilerTestCallbacks) as Key2;
|
||||
assert.ok(key2);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(key2.keys.length, 4);
|
||||
|
||||
const [q] = key2.keys.filter(({ id }) => id.value === 'q');
|
||||
assert.ok(q);
|
||||
assert.isFalse(!!(q.flags & constants.key2_key_flags_gap));
|
||||
assert.equal(q.width, 32, 'q\'s width'); // ceil(3.14159 * 10.0)
|
||||
assert.equal(q.flicks, 'flick0'); // note this is a string, not a StrsItem
|
||||
assert.equal(q.longPress.toString(), 'á é í');
|
||||
assert.equal(q.longPressDefault.value, 'é');
|
||||
assert.equal(q.multiTap.toString(), 'ä ë ï');
|
||||
|
||||
const [flick0] = key2.flicks.filter(({ id }) => id.value === 'flick0');
|
||||
assert.ok(flick0);
|
||||
assert.equal(flick0.flicks.length, 2);
|
||||
|
||||
const [flick0_nw_se] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('nw se'.split(' ')));
|
||||
assert.ok(flick0_nw_se);
|
||||
assert.equal(flick0_nw_se.to?.value, 'ç');
|
||||
|
||||
const [flick0_ne_sw] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('ne sw'.split(' ')));
|
||||
assert.ok(flick0_ne_sw);
|
||||
assert.equal(flick0_ne_sw.to?.value, 'ê');
|
||||
});
|
||||
|
||||
it('should compile escaped key2 data', function () {
|
||||
let key2 = loadSectionFixture(Key2Compiler, 'sections/key2/escaped.xml', compilerTestCallbacks) as Key2;
|
||||
assert.ok(key2);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(key2.keys.length, 4);
|
||||
|
||||
const [q] = key2.keys.filter(({ id }) => id.value === 'q');
|
||||
assert.ok(q);
|
||||
assert.isFalse(!!(q.flags & constants.key2_key_flags_gap));
|
||||
assert.equal(q.width, 32); // ceil(3.1 * 10)
|
||||
assert.equal(q.flicks, 'flick0'); // note this is a string, not a StrsItem
|
||||
assert.equal(q.longPress.toString(), 'á é í');
|
||||
assert.equal(q.longPressDefault.value, 'é');
|
||||
assert.equal(q.multiTap.toString(), 'ä ë ï');
|
||||
|
||||
const [flick0] = key2.flicks.filter(({ id }) => id.value === 'flick0');
|
||||
assert.ok(flick0);
|
||||
assert.equal(flick0.flicks.length, 2);
|
||||
|
||||
const [flick0_nw_se] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('nw se'.split(' ')));
|
||||
assert.ok(flick0_nw_se);
|
||||
assert.equal(flick0_nw_se.to?.value, 'ç');
|
||||
|
||||
const [flick0_ne_sw] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('ne sw'.split(' ')));
|
||||
assert.ok(flick0_ne_sw);
|
||||
assert.equal(flick0_ne_sw.to?.value, 'ế');
|
||||
});
|
||||
|
||||
|
||||
it('should accept layouts with gap/switch keys', function () {
|
||||
let key2 = loadSectionFixture(Key2Compiler, 'sections/keys/gap-switch.xml', compilerTestCallbacks) as Key2;
|
||||
assert.ok(key2);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(key2.keys.length, 4);
|
||||
|
||||
const [Qgap] = key2.keys.filter(({ id }) => id.value === 'Q');
|
||||
assert.ok(Qgap);
|
||||
assert.isTrue(!!(Qgap.flags & constants.key2_key_flags_gap), 'Q’s gap=');
|
||||
|
||||
const [Wshift] = key2.keys.filter(({ id }) => id.value === 'W');
|
||||
assert.isNotNull(Wshift);
|
||||
assert.isFalse(!!(Wshift.flags & constants.key2_key_flags_gap));
|
||||
assert.equal(Wshift.switch.value, 'shift');
|
||||
|
||||
});
|
||||
|
||||
testCompilationCases(Key2Compiler, [
|
||||
{
|
||||
subpath: 'sections/key2/escaped2.xml',
|
||||
callback: (key2, subpath, callbacks) => {
|
||||
assert.isNotNull(key2);
|
||||
assert.equal((<Key2>key2).keys.length, 1);
|
||||
const [q] = (<Key2>key2).keys.filter(({ id }) => id.value === 'grave');
|
||||
assert.equal(q.to.value, String.fromCodePoint(0x1faa6));
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,31 +1,128 @@
|
|||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { Key2Compiler } from '../src/compiler/key2.js';
|
||||
import { KeysCompiler } from '../src/compiler/keys.js';
|
||||
import { compilerTestCallbacks, loadSectionFixture, testCompilationCases } from './helpers/index.js';
|
||||
import { KMXPlus, Constants } from '@keymanapp/common-types';
|
||||
import { CompilerMessages } from '../src/compiler/messages.js';
|
||||
|
||||
import { constants } from '@keymanapp/ldml-keyboard-constants';
|
||||
import Keys = KMXPlus.Keys;
|
||||
const K = Constants.USVirtualKeyCodes;
|
||||
|
||||
import Key2 = KMXPlus.Key2;
|
||||
import { constants } from '@keymanapp/ldml-keyboard-constants';
|
||||
describe('keys', function () {
|
||||
this.slow(500); // 0.5 sec -- json schema validation takes a while
|
||||
|
||||
// Note: keeping the test cases, but they now apply to the subtable
|
||||
describe('key2.kmap', function () {
|
||||
it('should compile minimal keys data', function () {
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/minimal.xml', compilerTestCallbacks) as Keys;
|
||||
assert.ok(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 1);
|
||||
assert.equal(keys.flicks.length, 1); // there's always a 'null' flick
|
||||
assert.equal(keys.keys[0].to.value, '🪦');
|
||||
assert.equal(keys.keys[0].id.value, 'grave');
|
||||
});
|
||||
|
||||
it('should compile maximal keys data', function () {
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/maximal.xml', compilerTestCallbacks) as Keys;
|
||||
assert.ok(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 4);
|
||||
|
||||
const [q] = keys.keys.filter(({ id }) => id.value === 'q');
|
||||
assert.ok(q);
|
||||
assert.isFalse(!!(q.flags & constants.keys_key_flags_gap));
|
||||
assert.equal(q.width, 32, 'q\'s width'); // ceil(3.14159 * 10.0)
|
||||
assert.equal(q.flicks, 'flick0'); // note this is a string, not a StrsItem
|
||||
assert.equal(q.longPress.toString(), 'á é í');
|
||||
assert.equal(q.longPressDefault.value, 'é');
|
||||
assert.equal(q.multiTap.toString(), 'ä ë ï');
|
||||
|
||||
const [flick0] = keys.flicks.filter(({ id }) => id.value === 'flick0');
|
||||
assert.ok(flick0);
|
||||
assert.equal(flick0.flicks.length, 2);
|
||||
|
||||
const [flick0_nw_se] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('nw se'.split(' ')));
|
||||
assert.ok(flick0_nw_se);
|
||||
assert.equal(flick0_nw_se.to?.value, 'ç');
|
||||
|
||||
const [flick0_ne_sw] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('ne sw'.split(' ')));
|
||||
assert.ok(flick0_ne_sw);
|
||||
assert.equal(flick0_ne_sw.to?.value, 'ê');
|
||||
});
|
||||
|
||||
it('should compile escaped keys data', function () {
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/escaped.xml', compilerTestCallbacks) as Keys;
|
||||
assert.ok(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 4);
|
||||
|
||||
const [q] = keys.keys.filter(({ id }) => id.value === 'q');
|
||||
assert.ok(q);
|
||||
assert.isFalse(!!(q.flags & constants.keys_key_flags_gap));
|
||||
assert.equal(q.width, 32); // ceil(3.1 * 10)
|
||||
assert.equal(q.flicks, 'flick0'); // note this is a string, not a StrsItem
|
||||
assert.equal(q.longPress.toString(), 'á é í');
|
||||
assert.equal(q.longPressDefault.value, 'é');
|
||||
assert.equal(q.multiTap.toString(), 'ä ë ï');
|
||||
|
||||
const [flick0] = keys.flicks.filter(({ id }) => id.value === 'flick0');
|
||||
assert.ok(flick0);
|
||||
assert.equal(flick0.flicks.length, 2);
|
||||
|
||||
const [flick0_nw_se] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('nw se'.split(' ')));
|
||||
assert.ok(flick0_nw_se);
|
||||
assert.equal(flick0_nw_se.to?.value, 'ç');
|
||||
|
||||
const [flick0_ne_sw] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('ne sw'.split(' ')));
|
||||
assert.ok(flick0_ne_sw);
|
||||
assert.equal(flick0_ne_sw.to?.value, 'ế');
|
||||
});
|
||||
|
||||
|
||||
it('should accept layouts with gap/switch keys', function () {
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/gap-switch.xml', compilerTestCallbacks) as Keys;
|
||||
assert.ok(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 4);
|
||||
|
||||
const [Qgap] = keys.keys.filter(({ id }) => id.value === 'Q');
|
||||
assert.ok(Qgap);
|
||||
assert.isTrue(!!(Qgap.flags & constants.keys_key_flags_gap), 'Q’s gap=');
|
||||
|
||||
const [Wshift] = keys.keys.filter(({ id }) => id.value === 'W');
|
||||
assert.isNotNull(Wshift);
|
||||
assert.isFalse(!!(Wshift.flags & constants.keys_key_flags_gap));
|
||||
assert.equal(Wshift.switch.value, 'shift');
|
||||
|
||||
});
|
||||
|
||||
testCompilationCases(KeysCompiler, [
|
||||
{
|
||||
subpath: 'sections/keys/escaped2.xml',
|
||||
callback: (keys, subpath, callbacks) => {
|
||||
assert.isNotNull(keys);
|
||||
assert.equal((<Keys>keys).keys.length, 1);
|
||||
const [q] = (<Keys>keys).keys.filter(({ id }) => id.value === 'grave');
|
||||
assert.equal(q.to.value, String.fromCodePoint(0x1faa6));
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('keys.kmap', function () {
|
||||
this.slow(500); // 0.5 sec -- json schema validation takes a while
|
||||
|
||||
it('should compile minimal kmap data', function() {
|
||||
let key2 = loadSectionFixture(Key2Compiler, 'sections/keys/minimal.xml', compilerTestCallbacks) as Key2;
|
||||
assert.isNotNull(key2);
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/minimal.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNotNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(key2.kmap.length, 1);
|
||||
assert.equal(keys.kmap.length, 1);
|
||||
});
|
||||
|
||||
testCompilationCases(Key2Compiler, [
|
||||
testCompilationCases(KeysCompiler, [
|
||||
{
|
||||
subpath: 'sections/keys/hardware.xml',
|
||||
callback: (sect, subpath, callbacks) => {
|
||||
const keys = sect as Key2;
|
||||
const keys = sect as Keys;
|
||||
assert.isNotNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 4);
|
||||
|
|
@ -56,7 +153,7 @@ describe('key2.kmap', function () {
|
|||
{
|
||||
subpath: 'sections/keys/hardware_us.xml',
|
||||
callback: (sect, subpath, callbacks) => {
|
||||
const keys = sect as Key2;
|
||||
const keys = sect as Keys;
|
||||
assert.isNotNull(keys);
|
||||
assert.includeDeepMembers(keys.kmap, [
|
||||
{
|
||||
|
|
@ -80,7 +177,7 @@ describe('key2.kmap', function () {
|
|||
{
|
||||
subpath: 'sections/keys/hardware_iso.xml',
|
||||
callback: (sect, subpath, callbacks) => {
|
||||
const keys = sect as Key2;
|
||||
const keys = sect as Keys;
|
||||
assert.isNotNull(keys);
|
||||
assert.includeDeepMembers(keys.kmap, [
|
||||
{
|
||||
|
|
@ -110,7 +207,7 @@ describe('key2.kmap', function () {
|
|||
]);
|
||||
|
||||
it('should reject structurally invalid layers', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/invalid-missing-layer.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/invalid-missing-layer.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
|
||||
|
|
@ -118,7 +215,7 @@ describe('key2.kmap', function () {
|
|||
});
|
||||
|
||||
it('should reject layouts with too many hardware rows', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/invalid-hardware-too-many-rows.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/invalid-hardware-too-many-rows.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
|
||||
|
|
@ -126,7 +223,7 @@ describe('key2.kmap', function () {
|
|||
});
|
||||
|
||||
it('should reject layouts with too many hardware keys', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/invalid-hardware-too-many-keys.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/invalid-hardware-too-many-keys.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
|
||||
|
|
@ -134,20 +231,20 @@ describe('key2.kmap', function () {
|
|||
});
|
||||
|
||||
it('should reject layouts with undefined keys', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/invalid-undefined-key.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/invalid-undefined-key.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
|
||||
assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Error_KeyNotFoundInKeyBag({col: 1, form: 'hardware', keyId: 'foo', layer: 'base', row: 1}));
|
||||
});
|
||||
it('should reject layouts with invalid keys', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/invalid-key-missing-attrs.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/invalid-key-missing-attrs.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Error_KeyMissingToGapOrSwitch({keyId: 'Q'}));
|
||||
});
|
||||
it('should accept layouts with gap/switch keys', function() {
|
||||
let keys = loadSectionFixture(Key2Compiler, 'sections/keys/gap-switch.xml', compilerTestCallbacks) as Key2;
|
||||
let keys = loadSectionFixture(KeysCompiler, 'sections/keys/gap-switch.xml', compilerTestCallbacks) as Keys;
|
||||
assert.isNotNull(keys);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
assert.equal(keys.keys.length, 4);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ describe('layr', function () {
|
|||
assert.equal(row0.keys[0]?.value, 'grave');
|
||||
});
|
||||
|
||||
// reuse key2 maximal
|
||||
it('should compile maximal key2 data', function () {
|
||||
let layr = loadSectionFixture(LayrCompiler, 'sections/key2/maximal.xml', compilerTestCallbacks) as Layr;
|
||||
// reuse keys maximal
|
||||
it('should compile maximal keys data', function () {
|
||||
let layr = loadSectionFixture(LayrCompiler, 'sections/keys/maximal.xml', compilerTestCallbacks) as Layr;
|
||||
assert.ok(layr);
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue