~ruther/qmk_firmware

bb8d4b4d23ee04f6034f8880b8a9f93fa4673c38 — Ryan 5 years ago 93c5307
`send_unicode_string()`: Add support for code points > 0xFFFF (#8236)

M docs/feature_unicode.md => docs/feature_unicode.md +1 -2
@@ 195,7 195,7 @@ By default, when the keyboard boots, it will initialize the input mode to the la

## `send_unicode_string()`

This function is much like `send_string()` but allows you to input UTF-8 characters directly, currently up to code point U+FFFF. Make sure your `keymap.c` is formatted in UTF-8 encoding.
This function is much like `send_string()` but allows you to input UTF-8 characters directly, and supports all code points (provided the selected input method also supports it). Make sure your `keymap.c` is formatted in UTF-8 encoding.

```c
send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");


@@ 210,7 210,6 @@ send_unicode_hex_string("0028 30CE 0CA0 75CA 0CA0 0029 30CE 5F61 253B 2501 253B"
```

An easy way to convert your Unicode string to this format is by using [this site](https://r12a.github.io/app-conversion/), and taking the result in the "Hex/UTF-32" section.
Unlike `send_unicode_string()` this function supports code points up to U+10FFFF.

## Additional Language Support


M quantum/process_keycode/process_unicode_common.c => quantum/process_keycode/process_unicode_common.c +20 -4
@@ 150,6 150,24 @@ void register_hex(uint16_t hex) {
    }
}

void register_hex32(uint32_t hex) {
    bool onzerostart = true;
    for (int i = 7; i >= 0; i--) {
        if (i <= 3) {
            onzerostart = false;
        }
        uint8_t digit = ((hex >> (i * 4)) & 0xF);
        if (digit == 0) {
            if (!onzerostart) {
                tap_code(hex_to_keycode(digit));
            }
        } else {
            tap_code(hex_to_keycode(digit));
            onzerostart = false;
        }
    }
}

void send_unicode_hex_string(const char *str) {
    if (!str) {
        return;


@@ 192,9 210,7 @@ const char *decode_utf8(const char *str, int32_t *code_point) {
        *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;
        *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);
        next        = str + 4;
    } else {
        *code_point = -1;


@@ 221,7 237,7 @@ void send_unicode_string(const char *str) {

        if (code_point >= 0) {
            unicode_input_start();
            register_hex(code_point);
            register_hex32(code_point);
            unicode_input_finish();
        }
    }

M quantum/process_keycode/process_unicode_common.h => quantum/process_keycode/process_unicode_common.h +1 -0
@@ 79,6 79,7 @@ void unicode_input_finish(void);
void unicode_input_cancel(void);

void register_hex(uint16_t hex);
void register_hex32(uint32_t hex);
void send_unicode_hex_string(const char *str);
void send_unicode_string(const char *str);


M quantum/process_keycode/process_unicodemap.c => quantum/process_keycode/process_unicodemap.c +0 -20
@@ 16,26 16,6 @@

#include "process_unicodemap.h"

void register_hex32(uint32_t hex) {
    bool onzerostart = true;
    for (int i = 7; i >= 0; i--) {
        if (i <= 3) {
            onzerostart = false;
        }
        uint8_t digit = ((hex >> (i * 4)) & 0xF);
        if (digit == 0) {
            if (!onzerostart) {
                register_code(hex_to_keycode(digit));
                unregister_code(hex_to_keycode(digit));
            }
        } else {
            register_code(hex_to_keycode(digit));
            unregister_code(hex_to_keycode(digit));
            onzerostart = false;
        }
    }
}

__attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
    if (keycode >= QK_UNICODEMAP_PAIR) {
        // Keycode is a pair: extract index based on Shift / Caps Lock state

M quantum/process_keycode/process_unicodemap.h => quantum/process_keycode/process_unicodemap.h +0 -1
@@ 20,6 20,5 @@

extern const uint32_t PROGMEM unicode_map[];

void     register_hex32(uint32_t hex);
uint16_t unicodemap_index(uint16_t keycode);
bool     process_unicodemap(uint16_t keycode, keyrecord_t *record);