diff --git a/developer/src/kmc-convert/data/MySample.keylayout b/developer/src/kmc-convert/data/MySample.keylayout
index 23191ad7eb..2aa7e67fb2 100644
--- a/developer/src/kmc-convert/data/MySample.keylayout
+++ b/developer/src/kmc-convert/data/MySample.keylayout
@@ -77,6 +77,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts
index a315edd86d..841ec61d3d 100644
--- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts
+++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts
@@ -21,6 +21,13 @@ export class KeylayoutToKmnConverter {
// be available as class properties
}
+/**
+ * @brief run read/convert/write
+ * @param inputFilename the ukelele .keylayout-file to be converted
+ * @param outputFilename the resulting keyman .kmn-file
+ * @param binaryData ... _S2
+ * @return
+ */
async run(inputFilename: string, outputFilename: string, binaryData: Uint8Array): Promise {
if(!inputFilename || !outputFilename || !binaryData) {
@@ -51,86 +58,101 @@ export class KeylayoutToKmnConverter {
throw new Error('Not finished yet');
}
-// ............................................................................................................
-// ............................................................................................................
-// ............................................................................................................
+/**
+ * @brief read filename ( a .keylayout-file) and write contents into Uint8Array keys_all_Layers
+ * @param filename the ukelele .keylayout-file to be converted
+ * @return in case of success Uint8Array keys_all_Layers; else null
+ */
public read(filename: string):Uint8Array[] {
-/*
-- // _S2 TODO and what about deadkeys???
-- // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode)
-- // _S2 which stores?
-- // _S2 how to use names of shiftstates*/
+ /*
+ // _S2 TODO and what about deadkeys???
+ // _S2 TODO which format to use in output ? + [K_A] > 'a' (character code) or + [K_A] > U+0061 (virt Keycode)
+ // _S2 which stores?
+ */
const options = {
ignoreAttributes: false,
- attributeNamePrefix: '@_', // you have to assign this to use this to access the attribute
+ attributeNamePrefix: '@_', // to access the attribute
};
-
- //xml file from https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85)
const xmlFile = readFileSync(`${process.cwd()}/data/MySample.keylayout`, 'utf8');
const parser = new XMLParser(options);
const jsonObj = parser.parse(xmlFile); // get plain Object
const nrOfStates = jsonObj.keyboard.keyMapSet[0].keyMap.length
- const nrOfKeys = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length
+ const nrOfKeys_inLayer = jsonObj.keyboard.keyMapSet[0].keyMap[0].key.length
+
// create Object:any for storing Uint8tarray will be array[Uint8Array] Uint8Array might have several numbers (unicode)
- const Keys_all_Layers :any[] = []
+ // all keys for all layers
+ const keys_all_Layers :any[] = []
+ const modifier_array: any[] = [] // why not put modifiers into Uint8Array along with values of keys of layer
for (let j = 0; j < nrOfStates; j++) {
+
+ modifier_array[j] = jsonObj.keyboard.modifierMap.keyMapSelect[j].modifier['@_keys']
+
// create a new keys_in_Layer (type Uint8tarray)
- const keys_in_Layer :Uint8Array[] = []
- for (let i = 0; i < nrOfKeys; i++) {
- if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) {
- // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ])
- // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺
- const textencoder = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]);
- keys_in_Layer[i] = textencoder
- }
+ const keys_single_Layer :Uint8Array[] = []
+
+ for (let i = 0; i < nrOfKeys_inLayer; i++) {
+ if(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output'] !== "\0" ) {
+ // textencoder converts string -> bytes ( 'A' -> [ 65 ], '☺' -> [ 226, 152, 186 ])
+ // textencoder is of Uint8Array(1) for A and Uint8Array(3) for ☺
+ keys_single_Layer[i] = new TextEncoder().encode(jsonObj.keyboard.keyMapSet[0].keyMap[j].key[i]['@_output' ]);
}
- // add [nrOfStates] Objects:Uint8tarray to Keys_all_Layers
- Keys_all_Layers[j] = keys_in_Layer
- }
-
- console.log(" _S2 read finished\n")
- return(Keys_all_Layers.length === nrOfStates && Keys_all_Layers[0].length === nrOfKeys) ? Keys_all_Layers : null;
-}
-
-// ............................................................................................................
-
-public convert(inArray: any[]):any[] {
-
- const outArray :any[] = [];
- const nrOfMaxKeys = 50
-
- for (let j = 0; j < inArray.length ; j++) {
- const outkeys_in_Layer :Uint8Array[] = []
-
- // initialize keys
- for (let i = 0; i < nrOfMaxKeys; i++) {
- outkeys_in_Layer[i] = new TextEncoder().encode("\0");
}
- // now convert
- outkeys_in_Layer[0] = inArray[j][0];
- outkeys_in_Layer[24] = inArray[j][1];
- outkeys_in_Layer[2] = inArray[j][2];
- outkeys_in_Layer[1] = inArray[j][3];
- outkeys_in_Layer[16] = inArray[j][4];
- outkeys_in_Layer[29] = inArray[j][5];
- outkeys_in_Layer[38] = inArray[j][6];
- outkeys_in_Layer[46] = inArray[j][7];
-
- outArray[j] = outkeys_in_Layer
+ keys_all_Layers[j] = keys_single_Layer
}
- console.log(" _S2 convert finished\n")
- return (outArray.length === inArray.length ) ? outArray : null
+ // add the modifiers-> better idea?
+ keys_all_Layers[nrOfStates] = modifier_array
+
+ // Keys_all_Layers needs to have nrOfStates entries + 1 for modifiers
+ return((keys_all_Layers.length === nrOfStates + 1) && keys_all_Layers[0].length === nrOfKeys_inLayer) ? keys_all_Layers : null;
}
-public write(writeArray: any[]):boolean {
+/**
+ * @brief convert data of .keylayout-file to kmn-file This will convert/rename modifiers, position of Keys and deadkeys and save into an array
+ * @param data_ukelele (Uint8Array) data of the ukelele .keylayout-file
+ * @return outArray Uint8Array keys_all_Layers, the converted data for kmn-files if all layers have been converted; else null
+ */
+ public convert(data_ukelele: any[]):any[] {
+ // sorting order: alphabetically OK?
- const KeyArray = [
+ const data_kmn :any[] = [];
+
+ for (let j = 0; j < data_ukelele.length-1 ; j++) {
+ const keys_singleLayer :Uint8Array[] = []
+
+ // now convert & sort
+ keys_singleLayer[0] = data_ukelele[j][0];
+ keys_singleLayer[24] = data_ukelele[j][1];
+ keys_singleLayer[2] = data_ukelele[j][2];
+ keys_singleLayer[1] = data_ukelele[j][3];
+ keys_singleLayer[16] = data_ukelele[j][4];
+ keys_singleLayer[29] = data_ukelele[j][5];
+ keys_singleLayer[38] = data_ukelele[j][6];
+ keys_singleLayer[46] = data_ukelele[j][7];
+ // later more here...
+
+ data_kmn[j] = keys_singleLayer
+ }
+
+ //copy the modifier states
+ data_kmn[data_ukelele.length - 1] = data_ukelele[data_ukelele.length - 1]
+ console.log(" _S2 convert finished\n", data_kmn
+ )
+
+ return (data_kmn.length === data_ukelele.length ) ? data_kmn : null
+ }
+
+/** @brief write data to file
+ * @param kmn_array the array holding keyboard data
+ * @return true if data has been written; false if not
+ */
+ public write(kmn_array: any[]):boolean {
+ const kmn_Key_Name = [
'K_A','K_B','K_C','K_D','K_E','K_F','K_G','K_H','K_I','K_J','K_K','K_L','K_M','K_N','K_O','K_P','K_Q','K_R','K_S','K_T','K_U','K_V','K_W','K_X','K_Y','K_Z',
'K_0','K_1','K_2','K_3','K_4','K_5','K_6','K_7','K_8','K_9',
'K_SPACE',
@@ -156,16 +178,92 @@ public write(writeArray: any[]):boolean {
data += "group(main) using keys\n"
data += "\n"
- for (let i = 0; i < writeArray.length; i++) {
- for (let j = 0; j < writeArray[0].length; j++) {
- const textdecoder = new TextDecoder().decode(writeArray[i][j])
- if (textdecoder !== '\0' )
- data += `+ [` + KeyArray[j] + `] > \'` + textdecoder +'\'\n'
+ for (let i = 0; i < kmn_array.length-1; i++) {
+ for (let j = 0; j < kmn_array[0].length; j++) {
+
+ // get the modifier for the layer
+ const label_modifier = this.create_modifier(kmn_array[kmn_array.length-1][i])
+ // get the character that will be written as result in kmn-file
+ const resulting_character = new TextDecoder().decode(kmn_array[i][j])
+
+ // remove if-stmt later, only here for better visability
+ if (resulting_character !== '')
+ data += `+ [` + label_modifier + ' ' + kmn_Key_Name[j] + `] > \'` + resulting_character +'\'\n'
+
}
data += '\n'
}
+
writeFileSync("data/MyResult.kmn", data, { flag: "w"})
console.log(" _S2 write finished\n")
- return true;
+
+ if( data.length > 0)
+ return true;
+ else
+ return false
}
-}
\ No newline at end of file
+
+/**
+ * @brief check if search_modifier is available in modifier_array
+ * @param search_modifier the value that will be searched for in modifier_array
+ * @param modifier_array the array holding all modifiers used
+ * @return true if search_modifier is found; false if not
+ */
+ public isInArray(search_modifier:string, modifier_array: string[]):boolean {
+ for (let i =0; i < modifier_array.length; i++) {
+ if (search_modifier === String(modifier_array[i]))
+ return true
+ }
+ return false
+ }
+
+/**
+ * @brief create modifier in kmn-style from modifier of .keylayout-file
+ * @param keylayout_modifier the modifier value used in the .keylayout-file
+ * @return kmn_modifier the modifier value used in the .kmn-file
+ */
+ public create_modifier(keylayout_modifier:any):string {
+ let add_modifier = ""
+ let kmn_modifier = ""
+
+ // copy each modifier into element of array modifier_state
+ const modifier_state: string[] = keylayout_modifier.split(" ");
+
+ // TODO review these conditions-> what else do I need?
+ // TODO spelling entries of .keylayout( uppercase/lowercase, control<->ctrl,...)
+ // TODO anyOption?
+ // opt?+ LOPT?+ ROPT? -> what will be result??
+
+ for (let i = 0; i < modifier_state.length; i++) {
+
+ if ( String(modifier_state[i]) === "anyOption") add_modifier = "OPT "
+ else if ( String(modifier_state[i]) === "anyShift") add_modifier = "SHIFT "
+ else if ( String(modifier_state[i]) === "anyControl") add_modifier = "CTRL "
+
+ else if ( String(modifier_state[i]) === "anyOption?") add_modifier = "" // does anyOption?... happen?
+ else if ( String(modifier_state[i]) === "anyShift?") add_modifier = ""
+ else if ( String(modifier_state[i]) === "anyControl?") add_modifier = ""
+
+ else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state)) add_modifier = "RSHIFT "
+ else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('lshift',modifier_state)) add_modifier = "LSHIFT "
+ else if( (String(modifier_state[i]) === "shift?" ) && this.isInArray('rshift',modifier_state) && this.isInArray('lshift',modifier_state)) add_modifier = "SHIFT "
+
+ else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state)) add_modifier = "ROPT "
+ else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('lOption',modifier_state)) add_modifier = "LOPT "
+ else if( (String(modifier_state[i]) === "option?" ) && this.isInArray('rOption',modifier_state) && this.isInArray('lOption',modifier_state)) add_modifier = "OPT "
+
+ else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state)) add_modifier = "RCTRL "
+ else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('lControl',modifier_state)) add_modifier = "LCTRL "
+ else if( (String(modifier_state[i]) === "ctrl?" ) && this.isInArray('rControl',modifier_state) && this.isInArray('lControl',modifier_state)) add_modifier = "CTRL "
+
+ else if( String(modifier_state[i]) === "caps?") add_modifier = "" // capital letters or not?
+ else if( String(modifier_state[i]) === "shift?") add_modifier = ""
+ else if( String(modifier_state[i]) === "ctrl?") add_modifier = ""
+
+ else add_modifier = String(modifier_state[i])
+
+ kmn_modifier += add_modifier
+ }
+ return kmn_modifier.trim().toUpperCase()
+ }
+}