diff options
author | Ryan <fauxpark@gmail.com> | 2020-02-24 10:27:25 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-24 10:27:25 +1100 |
commit | 371ff9dd6f9c4feada34622d9a43480495b07e50 (patch) | |
tree | 785ba3038f5e431f1192c09f11d022c2c6850555 /quantum | |
parent | 716c29881c0f91e3998e1fc5c49740bd6e65876f (diff) |
A proper `send_string()` for the Unicode feature (#8155)
Diffstat (limited to 'quantum')
-rw-r--r-- | quantum/process_keycode/process_unicode_common.c | 49 | ||||
-rw-r--r-- | quantum/process_keycode/process_unicode_common.h | 1 |
2 files changed, 50 insertions, 0 deletions
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index 94383f19b7..4ac305e661 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 cab6eea6ea..393db2d99e 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); |