diff options
| -rw-r--r-- | docs/feature_unicode.md | 13 | ||||
| -rw-r--r-- | quantum/process_keycode/process_ucis.c | 97 | ||||
| -rw-r--r-- | quantum/process_keycode/process_ucis.h | 26 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode_common.c | 25 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode_common.h | 2 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicodemap.c | 21 | 
6 files changed, 89 insertions, 95 deletions
| diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md index a6f2cb4d0d..aedffe4ea2 100644 --- a/docs/feature_unicode.md +++ b/docs/feature_unicode.md @@ -66,13 +66,16 @@ Then define a table like this in your keymap file:  ```c  const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE( -    UCIS_SYM("poop", 0x1F4A9), // 💩 -    UCIS_SYM("rofl", 0x1F923), // 🤣 -    UCIS_SYM("kiss", 0x1F619)  // 😙 +    UCIS_SYM("poop", 0x1F4A9),                // 💩 +    UCIS_SYM("rofl", 0x1F923),                // 🤣 +    UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA),       // 🇨🇺 +    UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0), // ಠ_ಠ  );  ``` -To use it, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl"), and hit Space or Enter. QMK should erase the "rofl" text and insert the laughing emoji. +By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file. + +To use UCIS input, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.  ### Customization @@ -90,7 +93,7 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort  The following input modes are available: -* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map). +* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).    To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.    By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with another keycode. diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c index 024077317f..2541d6eb26 100644 --- a/quantum/process_keycode/process_ucis.c +++ b/quantum/process_keycode/process_ucis.c @@ -27,7 +27,7 @@ void qk_ucis_start(void) {  __attribute__((weak)) void qk_ucis_start_user(void) {      unicode_input_start(); -    register_hex(0x2328); +    register_hex(0x2328);  // ⌨      unicode_input_finish();  } @@ -35,74 +35,54 @@ __attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}  static bool is_uni_seq(char *seq) {      uint8_t i; -      for (i = 0; seq[i]; i++) { -        uint16_t code; -        if (('1' <= seq[i]) && (seq[i] <= '0')) -            code = seq[i] - '1' + KC_1; -        else -            code = seq[i] - 'a' + KC_A; - -        if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) return false; +        uint16_t keycode; +        if ('1' <= seq[i] && seq[i] <= '0') { +            keycode = seq[i] - '1' + KC_1; +        } else { +            keycode = seq[i] - 'a' + KC_A; +        } +        if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != keycode) { +            return false; +        }      } - -    return (qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC); +    return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;  }  __attribute__((weak)) void qk_ucis_symbol_fallback(void) {      for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) { -        uint8_t code = qk_ucis_state.codes[i]; -        register_code(code); -        unregister_code(code); +        uint8_t keycode = qk_ucis_state.codes[i]; +        register_code(keycode); +        unregister_code(keycode);          wait_ms(UNICODE_TYPE_DELAY);      }  }  __attribute__((weak)) void qk_ucis_cancel(void) {} -void register_ucis(const char *hex) { -    for (int i = 0; hex[i]; i++) { -        uint8_t kc = 0; -        char    c  = hex[i]; - -        switch (c) { -            case '0': -                kc = KC_0; -                break; -            case '1' ... '9': -                kc = c - '1' + KC_1; -                break; -            case 'a' ... 'f': -                kc = c - 'a' + KC_A; -                break; -            case 'A' ... 'F': -                kc = c - 'A' + KC_A; -                break; -        } - -        if (kc) { -            register_code(kc); -            unregister_code(kc); -            wait_ms(UNICODE_TYPE_DELAY); -        } +void register_ucis(const uint32_t *code_points) { +    for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) { +        register_unicode(code_points[i]); +        wait_ms(UNICODE_TYPE_DELAY);      }  }  bool process_ucis(uint16_t keycode, keyrecord_t *record) { -    uint8_t i; - -    if (!qk_ucis_state.in_progress) return true; +    if (!qk_ucis_state.in_progress || !record->event.pressed) { +        return true; +    } -    if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) { +    bool special = keycode == KC_SPC || keycode == KC_ENT || +                   keycode == KC_ESC || keycode == KC_BSPC; +    if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {          return false;      } -    if (!record->event.pressed) return true; -      qk_ucis_state.codes[qk_ucis_state.count] = keycode;      qk_ucis_state.count++; -    if (keycode == KC_BSPC) { +    switch (keycode) { +    case KC_BSPC:          if (qk_ucis_state.count >= 2) {              qk_ucis_state.count -= 2;              return true; @@ -110,12 +90,11 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {              qk_ucis_state.count--;              return false;          } -    } -    if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) { -        bool symbol_found = false; - -        for (i = qk_ucis_state.count; i > 0; i--) { +    case KC_SPC: +    case KC_ENT: +    case KC_ESC: +        for (uint8_t i = 0; i < qk_ucis_state.count; i++) {              register_code(KC_BSPC);              unregister_code(KC_BSPC);              wait_ms(UNICODE_TYPE_DELAY); @@ -127,25 +106,25 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {              return false;          } -        unicode_input_start(); +        uint8_t i; +        bool    symbol_found = false;          for (i = 0; ucis_symbol_table[i].symbol; i++) {              if (is_uni_seq(ucis_symbol_table[i].symbol)) {                  symbol_found = true; -                register_ucis(ucis_symbol_table[i].code + 2); +                register_ucis(ucis_symbol_table[i].code_points);                  break;              }          } -        if (!symbol_found) { -            qk_ucis_symbol_fallback(); -        } -        unicode_input_finish(); -          if (symbol_found) {              qk_ucis_success(i); +        } else { +            qk_ucis_symbol_fallback();          }          qk_ucis_state.in_progress = false;          return false; + +    default: +        return true;      } -    return true;  } diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h index 0f93a198bb..a667430bda 100644 --- a/quantum/process_keycode/process_ucis.h +++ b/quantum/process_keycode/process_ucis.h @@ -22,10 +22,13 @@  #ifndef UCIS_MAX_SYMBOL_LENGTH  #    define UCIS_MAX_SYMBOL_LENGTH 32  #endif +#ifndef UCIS_MAX_CODE_POINTS +#    define UCIS_MAX_CODE_POINTS 3 +#endif  typedef struct { -    char *symbol; -    char *code; +    char *   symbol; +    uint32_t code_points[UCIS_MAX_CODE_POINTS];  } qk_ucis_symbol_t;  typedef struct { @@ -36,12 +39,17 @@ typedef struct {  extern qk_ucis_state_t qk_ucis_state; -#define UCIS_TABLE(...)             \ -    {                               \ -        __VA_ARGS__, { NULL, NULL } \ +// clang-format off + +#define UCIS_TABLE(...) \ +    {                   \ +        __VA_ARGS__,    \ +        { NULL, {} }    \      } -#define UCIS_SYM(name, code) \ -    { name, #code } +#define UCIS_SYM(name, ...) \ +    { name, {__VA_ARGS__} } + +// clang-format on  extern const qk_ucis_symbol_t ucis_symbol_table[]; @@ -49,5 +57,7 @@ void qk_ucis_start(void);  void qk_ucis_start_user(void);  void qk_ucis_symbol_fallback(void);  void qk_ucis_success(uint8_t symbol_index); -void register_ucis(const char *hex); + +void register_ucis(const uint32_t *code_points); +  bool process_ucis(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index fb50215012..bea34c31ea 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -171,6 +171,25 @@ void register_hex32(uint32_t hex) {      }  } +void register_unicode(uint32_t code_point) { +    if (code_point > 0x10FFFF || (code_point > 0xFFFF && unicode_config.input_mode == UC_WIN)) { +        // Code point out of range, do nothing +        return; +    } + +    unicode_input_start(); +    if (code_point > 0xFFFF && unicode_config.input_mode == UC_MAC) { +        // Convert code point to UTF-16 surrogate pair on macOS +        code_point -= 0x10000; +        uint32_t lo = code_point & 0x3FF, hi = (code_point & 0xFFC00) >> 10; +        register_hex32(hi + 0xD800); +        register_hex32(lo + 0xDC00); +    } else { +        register_hex32(code_point); +    } +    unicode_input_finish(); +} +  // clang-format off  void send_unicode_hex_string(const char *str) { @@ -236,14 +255,12 @@ void send_unicode_string(const char *str) {          return;      } -    int32_t code_point = 0;      while (*str) { +        int32_t code_point = 0;          str = decode_utf8(str, &code_point);          if (code_point >= 0) { -            unicode_input_start(); -            register_hex32(code_point); -            unicode_input_finish(); +            register_unicode(code_point);          }      }  } diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h index 4579fde8d5..3082fbb5f0 100644 --- a/quantum/process_keycode/process_unicode_common.h +++ b/quantum/process_keycode/process_unicode_common.h @@ -89,6 +89,8 @@ void unicode_input_cancel(void);  void register_hex(uint16_t hex);  void register_hex32(uint32_t hex); +void register_unicode(uint32_t code_point); +  void send_unicode_hex_string(const char *str);  void send_unicode_string(const char *str); diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c index 2f402a2fd2..789a90445b 100644 --- a/quantum/process_keycode/process_unicodemap.c +++ b/quantum/process_keycode/process_unicodemap.c @@ -36,25 +36,8 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {  bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {      if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) { -        unicode_input_start(); - -        uint32_t code       = pgm_read_dword(unicode_map + unicodemap_index(keycode)); -        uint8_t  input_mode = get_unicode_input_mode(); - -        if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) { -            // Character is out of range supported by the platform -            unicode_input_cancel(); -        } else if (code > 0xFFFF && input_mode == UC_MAC) { -            // Convert to UTF-16 surrogate pair on Mac -            code -= 0x10000; -            uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10; -            register_hex32(hi + 0xD800); -            register_hex32(lo + 0xDC00); -            unicode_input_finish(); -        } else { -            register_hex32(code); -            unicode_input_finish(); -        } +        uint32_t code_point = pgm_read_dword(unicode_map + unicodemap_index(keycode)); +        register_unicode(code_point);      }      return true;  } | 
