From 371ff9dd6f9c4feada34622d9a43480495b07e50 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 24 Feb 2020 10:27:25 +1100 Subject: A proper `send_string()` for the Unicode feature (#8155) --- quantum/process_keycode/process_unicode_common.c | 49 ++++++++++++++++++++++++ quantum/process_keycode/process_unicode_common.h | 1 + 2 files changed, 50 insertions(+) (limited to 'quantum') diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index 94383f19b..4ac305e66 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -178,6 +178,55 @@ void send_unicode_hex_string(const char *str) { } } +// Borrowed from https://nullprogram.com/blog/2017/10/06/ +const char *decode_utf8(const char *str, int32_t *code_point) { + const char *next; + + if (str[0] < 0x80) { // U+0000-007F + *code_point = str[0]; + next = str + 1; + } else if ((str[0] & 0xE0) == 0xC0) { // U+0080-07FF + *code_point = ((int32_t)(str[0] & 0x1F) << 6) | ((int32_t)(str[1] & 0x3F) << 0); + next = str + 2; + } else if ((str[0] & 0xF0) == 0xE0) { // U+0800-FFFF + *code_point = ((int32_t)(str[0] & 0x0F) << 12) | ((int32_t)(str[1] & 0x3F) << 6) | ((int32_t)(str[2] & 0x3F) << 0); + next = str + 3; + } else if ((str[0] & 0xF8) == 0xF0 && (str[0] <= 0xF4)) { // U+10000-10FFFF + // Skip for now - register_hex() only takes a uint16 + //*code_point = ((int32_t)(str[0] & 0x07) << 18) | ((int32_t)(str[1] & 0x3F) << 12) | ((int32_t)(str[2] & 0x3F) << 6) | ((int32_t)(str[3] & 0x3F) << 0); + *code_point = -1; + next = str + 4; + } else { + *code_point = -1; + next = str + 1; + } + + // part of a UTF-16 surrogate pair - invalid + if (*code_point >= 0xD800 && *code_point <= 0xDFFF) { + *code_point = -1; + } + + return next; +} + +void send_unicode_string(const char *str) { + if (!str) { + return; + } + + int32_t code_point = 0; + + while (*str) { + str = decode_utf8(str, &code_point); + + if (code_point >= 0) { + unicode_input_start(); + register_hex(code_point); + unicode_input_finish(); + } + } +} + bool process_unicode_common(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { switch (keycode) { diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h index cab6eea6e..393db2d99 100644 --- a/quantum/process_keycode/process_unicode_common.h +++ b/quantum/process_keycode/process_unicode_common.h @@ -80,6 +80,7 @@ void unicode_input_cancel(void); void register_hex(uint16_t hex); void send_unicode_hex_string(const char *str); +void send_unicode_string(const char *str); bool process_unicode_common(uint16_t keycode, keyrecord_t *record); -- cgit v1.2.3