2019-01-26 15:54:29 +00:00
|
|
|
/**
|
|
|
|
* Author......: See docs/credits.txt
|
|
|
|
* License.....: MIT
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "filehandling.h"
|
|
|
|
#include "shared.h"
|
|
|
|
#include "keyboard_layout.h"
|
|
|
|
|
|
|
|
static int sort_by_src_len (const void *p1, const void *p2)
|
|
|
|
{
|
|
|
|
const keyboard_layout_mapping_t *k1 = (const keyboard_layout_mapping_t *) p1;
|
|
|
|
const keyboard_layout_mapping_t *k2 = (const keyboard_layout_mapping_t *) p2;
|
|
|
|
|
|
|
|
return k1->src_len < k2->src_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool initialize_keyboard_layout_mapping (const char *filename, keyboard_layout_mapping_t *keyboard_layout_mapping, int *keyboard_layout_mapping_cnt)
|
|
|
|
{
|
|
|
|
char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
|
|
|
|
|
2019-06-26 17:06:46 +00:00
|
|
|
HCFILE fp;
|
2019-01-26 15:54:29 +00:00
|
|
|
|
2019-06-30 23:30:24 +00:00
|
|
|
if (hc_fopen (&fp, filename, "r", HCFILE_FORMAT_PLAIN) == false) return false;
|
2019-01-26 15:54:29 +00:00
|
|
|
|
|
|
|
int maps_cnt = 0;
|
|
|
|
|
2019-06-26 17:06:46 +00:00
|
|
|
while (!hc_feof (&fp))
|
2019-01-26 15:54:29 +00:00
|
|
|
{
|
2019-06-26 17:06:46 +00:00
|
|
|
const size_t line_len = fgetl (&fp, line_buf);
|
2019-01-26 15:54:29 +00:00
|
|
|
|
|
|
|
if (line_len == 0) continue;
|
|
|
|
|
|
|
|
token_t token;
|
|
|
|
|
|
|
|
token.token_cnt = 2;
|
|
|
|
|
|
|
|
token.len_min[0] = 1;
|
|
|
|
token.len_max[0] = 4;
|
|
|
|
token.sep[0] = 0x09;
|
|
|
|
token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH;
|
|
|
|
|
|
|
|
token.len_min[1] = 0;
|
|
|
|
token.len_max[1] = 4;
|
|
|
|
token.sep[1] = 0x09;
|
|
|
|
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH;
|
|
|
|
|
|
|
|
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, (const int) line_len, &token);
|
|
|
|
|
|
|
|
if (rc_tokenizer != PARSER_OK)
|
|
|
|
{
|
2019-06-26 17:06:46 +00:00
|
|
|
hc_fclose (&fp);
|
2019-01-26 15:54:29 +00:00
|
|
|
|
|
|
|
free (line_buf);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy (&keyboard_layout_mapping[maps_cnt].src_char, token.buf[0], token.len[0]);
|
|
|
|
memcpy (&keyboard_layout_mapping[maps_cnt].dst_char, token.buf[1], token.len[1]);
|
|
|
|
|
|
|
|
keyboard_layout_mapping[maps_cnt].src_len = token.len[0];
|
|
|
|
keyboard_layout_mapping[maps_cnt].dst_len = token.len[1];
|
|
|
|
|
|
|
|
if (maps_cnt == 256)
|
|
|
|
{
|
2019-06-26 17:06:46 +00:00
|
|
|
hc_fclose (&fp);
|
2019-01-26 15:54:29 +00:00
|
|
|
|
|
|
|
free (line_buf);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
maps_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*keyboard_layout_mapping_cnt = maps_cnt;
|
|
|
|
|
2019-06-26 17:06:46 +00:00
|
|
|
hc_fclose (&fp);
|
2019-01-26 15:54:29 +00:00
|
|
|
|
|
|
|
free (line_buf);
|
|
|
|
|
|
|
|
// we need to sort this by length to ensure the largest blocks come first in mapping
|
|
|
|
|
|
|
|
qsort (keyboard_layout_mapping, maps_cnt, sizeof (keyboard_layout_mapping_t), sort_by_src_len);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-07 16:15:45 +00:00
|
|
|
int find_keyboard_layout_map (const u32 search, const int search_len, const keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
2019-01-26 15:54:29 +00:00
|
|
|
{
|
|
|
|
for (int idx = 0; idx < keyboard_layout_mapping_cnt; idx++)
|
|
|
|
{
|
|
|
|
const u32 src_char = s_keyboard_layout_mapping[idx].src_char;
|
|
|
|
const int src_len = s_keyboard_layout_mapping[idx].src_len;
|
|
|
|
|
|
|
|
if (src_len == search_len)
|
|
|
|
{
|
|
|
|
const u32 mask = 0xffffffff >> ((4 - search_len) * 8);
|
|
|
|
|
|
|
|
if ((src_char & mask) == (search & mask)) return idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-02-07 16:15:45 +00:00
|
|
|
int execute_keyboard_layout_mapping (u32 plain_buf[64], const int plain_len, const keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
2019-01-26 15:54:29 +00:00
|
|
|
{
|
|
|
|
u32 out_buf[16] = { 0 };
|
|
|
|
|
|
|
|
u8 *out_ptr = (u8 *) out_buf;
|
|
|
|
|
|
|
|
int out_len = 0;
|
|
|
|
|
|
|
|
u8 *plain_ptr = (u8 *) plain_buf;
|
|
|
|
|
|
|
|
int plain_pos = 0;
|
|
|
|
|
|
|
|
while (plain_pos < plain_len)
|
|
|
|
{
|
|
|
|
u32 src0 = 0;
|
|
|
|
u32 src1 = 0;
|
|
|
|
u32 src2 = 0;
|
|
|
|
u32 src3 = 0;
|
|
|
|
|
|
|
|
const int rem = MIN (plain_len - plain_pos, 4);
|
|
|
|
|
|
|
|
if (rem > 0) src0 = plain_ptr[plain_pos + 0];
|
|
|
|
if (rem > 1) src1 = plain_ptr[plain_pos + 1];
|
|
|
|
if (rem > 2) src2 = plain_ptr[plain_pos + 2];
|
|
|
|
if (rem > 3) src3 = plain_ptr[plain_pos + 3];
|
|
|
|
|
|
|
|
const u32 src = (src0 << 0)
|
|
|
|
| (src1 << 8)
|
|
|
|
| (src2 << 16)
|
|
|
|
| (src3 << 24);
|
|
|
|
|
|
|
|
int src_len;
|
|
|
|
|
|
|
|
for (src_len = rem; src_len > 0; src_len--)
|
|
|
|
{
|
|
|
|
const int idx = find_keyboard_layout_map (src, src_len, s_keyboard_layout_mapping, keyboard_layout_mapping_cnt);
|
|
|
|
|
|
|
|
if (idx == -1) continue;
|
|
|
|
|
|
|
|
u32 dst_char = s_keyboard_layout_mapping[idx].dst_char;
|
|
|
|
int dst_len = s_keyboard_layout_mapping[idx].dst_len;
|
|
|
|
|
|
|
|
switch (dst_len)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
|
|
|
out_ptr[out_len++] = (dst_char >> 24) & 0xff;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
plain_pos += src_len;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// not matched, keep original
|
|
|
|
|
|
|
|
if (src_len == 0)
|
|
|
|
{
|
|
|
|
out_ptr[out_len] = plain_ptr[plain_pos];
|
|
|
|
|
|
|
|
out_len++;
|
|
|
|
|
|
|
|
plain_pos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
plain_buf[ 0] = out_buf[ 0];
|
|
|
|
plain_buf[ 1] = out_buf[ 1];
|
|
|
|
plain_buf[ 2] = out_buf[ 2];
|
|
|
|
plain_buf[ 3] = out_buf[ 3];
|
|
|
|
plain_buf[ 4] = out_buf[ 4];
|
|
|
|
plain_buf[ 5] = out_buf[ 5];
|
|
|
|
plain_buf[ 6] = out_buf[ 6];
|
|
|
|
plain_buf[ 7] = out_buf[ 7];
|
|
|
|
plain_buf[ 8] = out_buf[ 8];
|
|
|
|
plain_buf[ 9] = out_buf[ 9];
|
|
|
|
plain_buf[10] = out_buf[10];
|
|
|
|
plain_buf[11] = out_buf[11];
|
|
|
|
plain_buf[12] = out_buf[12];
|
|
|
|
plain_buf[13] = out_buf[13];
|
|
|
|
plain_buf[14] = out_buf[14];
|
|
|
|
plain_buf[15] = out_buf[15];
|
|
|
|
|
|
|
|
return out_len;
|
|
|
|
}
|