/** * 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) { HCFILE fp; if (hc_fopen (&fp, filename, "r") == false) return false; char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE); int maps_cnt = 0; while (!hc_feof (&fp)) { const size_t line_len = fgetl (&fp, line_buf, HCBUFSIZ_LARGE); if (line_len == 0) continue; hc_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; if (input_tokenizer ((const u8 *) line_buf, (const int) line_len, &token) != PARSER_OK) { hc_fclose (&fp); hcfree (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) { hc_fclose (&fp); hcfree (line_buf); return false; } maps_cnt++; } *keyboard_layout_mapping_cnt = maps_cnt; hc_fclose (&fp); hcfree (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; } 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) { 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; } 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) { 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; }