diff options
Diffstat (limited to 'quantum/process_keycode')
| -rw-r--r-- | quantum/process_keycode/autocorrect_data_default.h | 85 | ||||
| -rw-r--r-- | quantum/process_keycode/process_autocorrect.c | 287 | ||||
| -rw-r--r-- | quantum/process_keycode/process_autocorrect.h | 17 | ||||
| -rw-r--r-- | quantum/process_keycode/process_leader.c | 2 | ||||
| -rw-r--r-- | quantum/process_keycode/process_ucis.c | 17 | ||||
| -rw-r--r-- | quantum/process_keycode/process_ucis.h | 6 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode.c | 12 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode.h | 5 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode_common.c | 298 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicode_common.h | 184 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicodemap.c | 5 | ||||
| -rw-r--r-- | quantum/process_keycode/process_unicodemap.h | 6 | 
12 files changed, 432 insertions, 492 deletions
| diff --git a/quantum/process_keycode/autocorrect_data_default.h b/quantum/process_keycode/autocorrect_data_default.h new file mode 100644 index 0000000000..bfc29666df --- /dev/null +++ b/quantum/process_keycode/autocorrect_data_default.h @@ -0,0 +1,85 @@ +// Generated code. + +// Autocorrection dictionary (70 entries): +//   :guage     -> gauge +//   :the:the:  -> the +//   :thier     -> their +//   :ture      -> true +//   accomodate -> accommodate +//   acommodate -> accommodate +//   aparent    -> apparent +//   aparrent   -> apparent +//   apparant   -> apparent +//   apparrent  -> apparent +//   aquire     -> acquire +//   becuase    -> because +//   cauhgt     -> caught +//   cheif      -> chief +//   choosen    -> chosen +//   cieling    -> ceiling +//   collegue   -> colleague +//   concensus  -> consensus +//   contians   -> contains +//   cosnt      -> const +//   dervied    -> derived +//   fales      -> false +//   fasle      -> false +//   fitler     -> filter +//   flase      -> false +//   foward     -> forward +//   frequecy   -> frequency +//   gaurantee  -> guarantee +//   guaratee   -> guarantee +//   heigth     -> height +//   heirarchy  -> hierarchy +//   inclued    -> include +//   interator  -> iterator +//   intput     -> input +//   invliad    -> invalid +//   lenght     -> length +//   liasion    -> liaison +//   libary     -> library +//   listner    -> listener +//   looses:    -> loses +//   looup      -> lookup +//   manefist   -> manifest +//   namesapce  -> namespace +//   namespcae  -> namespace +//   occassion  -> occasion +//   occured    -> occurred +//   ouptut     -> output +//   ouput      -> output +//   overide    -> override +//   postion    -> position +//   priviledge -> privilege +//   psuedo     -> pseudo +//   recieve    -> receive +//   refered    -> referred +//   relevent   -> relevant +//   repitition -> repetition +//   retrun     -> return +//   retun      -> return +//   reuslt     -> result +//   reutrn     -> return +//   saftey     -> safety +//   seperate   -> separate +//   singed     -> signed +//   stirng     -> string +//   strign     -> string +//   swithc     -> switch +//   swtich     -> switch +//   thresold   -> threshold +//   udpate     -> update +//   widht      -> width + +#define AUTOCORRECT_MIN_LENGTH 5  // ":ture" +#define AUTOCORRECT_MAX_LENGTH 10 // "accomodate" + +#define DICTIONARY_SIZE 1104 + +static const uint8_t autocorrect_data[DICTIONARY_SIZE] PROGMEM = {108, 43,  0,   6,   71, 0,  7,   81, 0,   8,   199, 0,   9,   240, 1,  10,  250, 1,  11,  26,  2,   17,  53,  2,   18, 190, 2,   19,  202, 2,   21,  212, 2,   22,  20,  3,   23,  67,  3,   28,  16,  4,   0,  72,  50,  0,   22,  60,  0,   0,   11,  23,  44, 8,   11, 23,  44,  0,   132, 0,   8,   22,  18,  18,  15,  0,  132, 115, 101, 115, 0,   11,  23,  12,  26,  22,  0,   129, 99,  104, 0,   68,  94,  0,   8,   106, 0,   15, 174, 0,   21, 187, 0,   0,   12,  15,  25,  17,  12,  0,   131, 97,  108, 105, 100, 0,   74,  119, 0,   12,  129, 0,   21,  140, 0,   24,  165, 0,   0,   17,  12,  22,  0,   131, 103, 110, 101, 100, 0,   25,  21, 8,   7,   0,   131, 105, 118, 101, 100, 0,   72,  147, 0,  24,  156, 0,  0,   9,   8,   21,  0,   129, 114, 101, 100, 0,   6,   6,   18,  0,   129, 114, 101, 100, 0,   15,  6,   17,  12,  0,   129, 100, 101, 0,   18, 22,  8,   21,  11,  23,  0,   130, 104, 111, +                                                                  108, 100, 0,   4,   26, 18, 9,   0,  131, 114, 119, 97,  114, 100, 0,  68,  233, 0,  6,   246, 0,   7,   4,   1,   8,  16,  1,   10,  52,  1,   15,  81,  1,   21,  90,  1,   22,  117, 1,   23,  144, 1,   24, 215, 1,   25,  228, 1,   0,   6,   19,  22,  8,  16,  4,  17,  0,   130, 97,  99,  101, 0,   19,  4,   22,  8,  16,  4,   17,  0,   131, 112, 97,  99,  101, 0,   12,  21,  8,   25,  18,  0,   130, 114, 105, 100, 101, 0,  23,  0,   68, 25,  1,   17,  36,  1,   0,   21,  4,   24,  10,  0,   130, 110, 116, 101, 101, 0,   4,   21,  24,  4,   10,  0,   135, 117, 97,  114, 97,  110, 116, 101, 101, 0,   68,  59,  1,   7,   69,  1,   0,  24,  10,  44,  0,   131, 97,  117, 103, 101, 0,   8,   15, 12,  25,  12, 21,  19,  0,   130, 103, 101, 0,   22,  4,   9,   0,   130, 108, 115, 101, 0,   76,  97,  1,   24,  109, 1,   0,   24,  20,  4,   0,   132, 99, 113, 117, 105, 114, 101, 0,   23,  44,  0, +                                                                  130, 114, 117, 101, 0,  4,  0,   79, 126, 1,   24,  134, 1,   0,   9,  0,   131, 97, 108, 115, 101, 0,   6,   8,   5,  0,   131, 97,  117, 115, 101, 0,   4,   0,   71,  156, 1,   19,  193, 1,   21,  203, 1,  0,   18,  16,  0,   80,  166, 1,   18,  181, 1,  0,   18, 6,   4,   0,   135, 99,  111, 109, 109, 111, 100, 97, 116, 101, 0,   6,   6,   4,   0,   132, 109, 111, 100, 97,  116, 101, 0,   7,   24,  0,   132, 112, 100, 97, 116, 101, 0,  8,   19,  8,   22,  0,   132, 97,  114, 97,  116, 101, 0,   10,  8,   15,  15,  18,  6,   0,   130, 97,  103, 117, 101, 0,   8,   12,  6,   8,   21,  0,   131, 101, 105, 118, 101, 0,   12,  8,   11, 6,   0,   130, 105, 101, 102, 0,   17,  0,   76,  3,   2,  21,  16,  2,  0,   15,  8,   12,  6,   0,   133, 101, 105, 108, 105, 110, 103, 0,   12,  23,  22,  0,   131, 114, 105, 110, 103, 0,   70,  33,  2,   23,  44, 2,   0,   12,  23,  26,  22,  0,   131, 105, +                                                                  116, 99,  104, 0,   10, 12, 8,   11, 0,   129, 104, 116, 0,   72,  69, 2,   10,  80, 2,   18,  89,  2,   21,  156, 2,  24,  167, 2,   0,   22,  18,  18,  11,  6,   0,   131, 115, 101, 110, 0,   12,  21,  23, 22,  0,   129, 110, 103, 0,   12,  0,   86,  98, 2,   23, 124, 2,   0,   68,  105, 2,   22,  114, 2,   0,   12, 15,  0,   131, 105, 115, 111, 110, 0,   4,   6,   6,   18,  0,   131, 105, 111, 110, 0,   76,  131, 2,   22, 146, 2,   0,  23,  12,  19,  8,   21,  0,   134, 101, 116, 105, 116, 105, 111, 110, 0,   18,  19,  0,   131, 105, 116, 105, 111, 110, 0,   23,  24,  8,   21,  0,   131, 116, 117, 114, 110, 0,   85,  174, 2,   23, 183, 2,   0,   23,  8,   21,  0,   130, 117, 114, 110, 0,  8,   21,  0,  128, 114, 110, 0,   7,   8,   24,  22,  19,  0,   131, 101, 117, 100, 111, 0,   24,  18,  18,  15,  0,   129, 107, 117, 112, 0,   72,  219, 2,  18,  3,   3,   0,   76,  229, 2,   15,  238, +                                                                  2,   17,  248, 2,   0,  11, 23,  44, 0,   130, 101, 105, 114, 0,   23, 12,  9,   0,  131, 108, 116, 101, 114, 0,   23, 22,  12,  15,  0,   130, 101, 110, 101, 114, 0,   23,  4,   21,  8,   23,  17,  12,  0,  135, 116, 101, 114, 97,  116, 111, 114, 0,   72, 30,  3,  17,  38,  3,   24,  51,  3,   0,   15,  4,   9,   0,  129, 115, 101, 0,   4,   12,  23,  17,  18,  6,   0,   131, 97,  105, 110, 115, 0,   22,  17,  8,   6,   17, 18,  6,   0,  133, 115, 101, 110, 115, 117, 115, 0,   74,  86,  3,   11,  96,  3,   15,  118, 3,   17,  129, 3,   22,  218, 3,   24,  232, 3,   0,   11,  24,  4,   6,   0,   130, 103, 104, 116, 0,   71,  103, 3,  10,  110, 3,   0,   12,  26,  0,   129, 116, 104, 0,   17, 8,   15,  0,  129, 116, 104, 0,   22,  24,  8,   21,  0,   131, 115, 117, 108, 116, 0,   68,  139, 3,   8,   150, 3,   22,  210, 3,   0,   21,  4,   19,  19, 4,   0,   130, 101, 110, 116, 0,   85,  157, +                                                                  3,   25,  200, 3,   0,  68, 164, 3,  21,  175, 3,   0,   19,  4,   0,  132, 112, 97, 114, 101, 110, 116, 0,   4,   19, 0,   68,  185, 3,   19,  193, 3,   0,   133, 112, 97,  114, 101, 110, 116, 0,   4,   0,  131, 101, 110, 116, 0,   8,   15,  8,   21,  0,  130, 97, 110, 116, 0,   18,  6,   0,   130, 110, 115, 116, 0,  12,  9,   8,   17,  4,   16,  0,   132, 105, 102, 101, 115, 116, 0,   83,  239, 3,   23,  6,   4,   0,   87, 246, 3,   24, 254, 3,   0,   17,  12,  0,   131, 112, 117, 116, 0,   18,  0,   130, 116, 112, 117, 116, 0,   19,  24,  18,  0,   131, 116, 112, 117, 116, 0,   70,  29,  4,   8,   41,  4,   11,  51,  4,   21,  69, 4,   0,   8,   24,  20,  8,   21,  9,   0,   129, 110, 99, 121, 0,   23, 9,   4,   22,  0,   130, 101, 116, 121, 0,   6,   21,  4,   21,  12,  8,   11,  0,   135, 105, 101, 114, 97,  114, 99,  104, 121, 0,   4,   5,  12,  15,  0,   130, 114, 97,  114, 121, 0}; diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c new file mode 100644 index 0000000000..abae5e7811 --- /dev/null +++ b/quantum/process_keycode/process_autocorrect.c @@ -0,0 +1,287 @@ +// Copyright 2021 Google LLC +// Copyright 2021 @filterpaper +// SPDX-License-Identifier: Apache-2.0 +// Original source: https://getreuer.info/posts/keyboards/autocorrection + +#include "process_autocorrect.h" +#include <string.h> +#include "keycode_config.h" + +#if __has_include("autocorrect_data.h") +#    include "autocorrect_data.h" +#else +#    pragma message "Autocorrect is using the default library." +#    include "autocorrect_data_default.h" +#endif + +static uint8_t typo_buffer[AUTOCORRECT_MAX_LENGTH] = {KC_SPC}; +static uint8_t typo_buffer_size                    = 1; + +/** + * @brief function for querying the enabled state of autocorrect + * + * @return true if enabled + * @return false if disabled + */ +bool autocorrect_is_enabled(void) { +    return keymap_config.autocorrect_enable; +} + +/** + * @brief Enables autocorrect and saves state to eeprom + * + */ +void autocorrect_enable(void) { +    keymap_config.autocorrect_enable = true; +    eeconfig_update_keymap(keymap_config.raw); +} + +/** + * @brief Disables autocorrect and saves state to eeprom + * + */ +void autocorrect_disable(void) { +    keymap_config.autocorrect_enable = false; +    typo_buffer_size                 = 0; +    eeconfig_update_keymap(keymap_config.raw); +} + +/** + * @brief Toggles autocorrect's status and save state to eeprom + * + */ +void autocorrect_toggle(void) { +    keymap_config.autocorrect_enable = !keymap_config.autocorrect_enable; +    typo_buffer_size                 = 0; +    eeconfig_update_keymap(keymap_config.raw); +} + +/** + * @brief handler for determining if autocorrect should process keypress + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @param typo_buffer_size passed along to allow resetting of autocorrect buffer + * @param mods allow processing of mod status + * @return true Allow autocorection + * @return false Stop processing and escape from autocorrect. + */ +__attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { +    // See quantum_keycodes.h for reference on these matched ranges. +    switch (*keycode) { +        // Exclude these keycodes from processing. +        case KC_LSFT: +        case KC_RSFT: +        case KC_CAPS: +        case QK_TO ... QK_ONE_SHOT_LAYER_MAX: +        case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX: +        case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: +            return false; + +        // Mask for base keycode from shifted keys. +        case QK_LSFT ... QK_LSFT + 255: +        case QK_RSFT ... QK_RSFT + 255: +            if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) { +                *mods |= MOD_LSFT; +            } else { +                *mods |= MOD_RSFT; +            } +            *keycode &= 0xFF; // Get the basic keycode. +            return true; +#ifndef NO_ACTION_TAPPING +        // Exclude tap-hold keys when they are held down +        // and mask for base keycode when they are tapped. +        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: +#    ifdef NO_ACTION_LAYER +            // Exclude Layer Tap, if layers are disabled +            // but action tapping is still enabled. +            return false; +#    endif +        case QK_MOD_TAP ... QK_MOD_TAP_MAX: +            // Exclude hold keycode +            if (!record->tap.count) { +                return false; +            } +            *keycode &= 0xFF; +            break; +#else +        case QK_MOD_TAP ... QK_MOD_TAP_MAX: +        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: +            // Exclude if disabled +            return false; +#endif +        // Exclude swap hands keys when they are held down +        // and mask for base keycode when they are tapped. +        case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: +#ifdef SWAP_HANDS_ENABLE +            if (*keycode >= 0x56F0 || !record->tap.count) { +                return false; +            } +            *keycode &= 0xFF; +            break; +#else +            // Exclude if disabled +            return false; +#endif +    } + +    // Disable autocorrect while a mod other than shift is active. +    if ((*mods & ~MOD_MASK_SHIFT) != 0) { +        *typo_buffer_size = 0; +        return false; +    } + +    return true; +} + +/** + * @brief handling for when autocorrection has been triggered + * + * @param backspaces number of characters to remove + * @param str pointer to PROGMEM string to replace mistyped seletion with + * @return true apply correction + * @return false user handled replacement + */ +__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { +    return true; +} + +/** + * @brief Process handler for autocorrect feature + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @return true Continue processing keycodes, and send to host + * @return false Stop processing keycodes, and don't send to host + */ +bool process_autocorrect(uint16_t keycode, keyrecord_t *record) { +    uint8_t mods = get_mods(); +#ifndef NO_ACTION_ONESHOT +    mods |= get_oneshot_mods(); +#endif + +    if ((keycode >= AUTOCORRECT_ON && keycode <= AUTOCORRECT_TOGGLE) && record->event.pressed) { +        if (keycode == AUTOCORRECT_ON) { +            autocorrect_enable(); +        } else if (keycode == AUTOCORRECT_OFF) { +            autocorrect_disable(); +        } else if (keycode == AUTOCORRECT_TOGGLE) { +            autocorrect_toggle(); +        } else { +            return true; +        } + +        return false; +    } + +    if (!keymap_config.autocorrect_enable) { +        typo_buffer_size = 0; +        return true; +    } + +    if (!record->event.pressed) { +        return true; +    } + +    // autocorrect keycode verification and extraction +    if (!process_autocorrect_user(&keycode, record, &typo_buffer_size, &mods)) { +        return true; +    } + +    // keycode buffer check +    switch (keycode) { +        case KC_A ... KC_Z: +            // process normally +            break; +        case KC_1 ... KC_0: +        case KC_TAB ... KC_SEMICOLON: +        case KC_GRAVE ... KC_SLASH: +            // Set a word boundary if space, period, digit, etc. is pressed. +            keycode = KC_SPC; +            break; +        case KC_ENTER: +            // Behave more conservatively for the enter key. Reset, so that enter +            // can't be used on a word ending. +            typo_buffer_size = 0; +            keycode          = KC_SPC; +            break; +        case KC_BSPC: +            // Remove last character from the buffer. +            if (typo_buffer_size > 0) { +                --typo_buffer_size; +            } +            return true; +        case KC_QUOTE: +            // Treat " (shifted ') as a word boundary. +            if ((mods & MOD_MASK_SHIFT) != 0) { +                keycode = KC_SPC; +            } +            break; +        default: +            // Clear state if some other non-alpha key is pressed. +            typo_buffer_size = 0; +            return true; +    } + +    // Rotate oldest character if buffer is full. +    if (typo_buffer_size >= AUTOCORRECT_MAX_LENGTH) { +        memmove(typo_buffer, typo_buffer + 1, AUTOCORRECT_MAX_LENGTH - 1); +        typo_buffer_size = AUTOCORRECT_MAX_LENGTH - 1; +    } + +    // Append `keycode` to buffer. +    typo_buffer[typo_buffer_size++] = keycode; +    // Return if buffer is smaller than the shortest word. +    if (typo_buffer_size < AUTOCORRECT_MIN_LENGTH) { +        return true; +    } + +    // Check for typo in buffer using a trie stored in `autocorrect_data`. +    uint16_t state = 0; +    uint8_t  code  = pgm_read_byte(autocorrect_data + state); +    for (int8_t i = typo_buffer_size - 1; i >= 0; --i) { +        uint8_t const key_i = typo_buffer[i]; + +        if (code & 64) { // Check for match in node with multiple children. +            code &= 63; +            for (; code != key_i; code = pgm_read_byte(autocorrect_data + (state += 3))) { +                if (!code) return true; +            } +            // Follow link to child node. +            state = (pgm_read_byte(autocorrect_data + state + 1) | pgm_read_byte(autocorrect_data + state + 2) << 8); +            // Check for match in node with single child. +        } else if (code != key_i) { +            return true; +        } else if (!(code = pgm_read_byte(autocorrect_data + (++state)))) { +            ++state; +        } + +        // Stop if `state` becomes an invalid index. This should not normally +        // happen, it is a safeguard in case of a bug, data corruption, etc. +        if (state >= DICTIONARY_SIZE) { +            return true; +        } + +        code = pgm_read_byte(autocorrect_data + state); + +        if (code & 128) { // A typo was found! Apply autocorrect. +            const uint8_t backspaces = (code & 63) + !record->event.pressed; +            if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { +                for (uint8_t i = 0; i < backspaces; ++i) { +                    tap_code(KC_BSPC); +                } +                send_string_P((char const *)(autocorrect_data + state + 1)); +            } + +            if (keycode == KC_SPC) { +                typo_buffer[0]   = KC_SPC; +                typo_buffer_size = 1; +                return true; +            } else { +                typo_buffer_size = 0; +                return false; +            } +        } +    } +    return true; +} diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h new file mode 100644 index 0000000000..c7596107e5 --- /dev/null +++ b/quantum/process_keycode/process_autocorrect.h @@ -0,0 +1,17 @@ +// Copyright 2021 Google LLC +// Copyright 2021 @filterpaper +// SPDX-License-Identifier: Apache-2.0 +// Original source: https://getreuer.info/posts/keyboards/autocorrection + +#pragma once + +#include "quantum.h" + +bool process_autocorrect(uint16_t keycode, keyrecord_t *record); +bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); +bool apply_autocorrect(uint8_t backspaces, const char *str); + +bool autocorrect_is_enabled(void); +void autocorrect_enable(void); +void autocorrect_disable(void); +void autocorrect_toggle(void); diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index ae00b3227a..3593f75f0d 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -58,7 +58,7 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {                      keycode = keycode & 0xFF;                  }  #    endif // LEADER_KEY_STRICT_KEY_PROCESSING -                if (leader_sequence_size < (sizeof(leader_sequence) / sizeof(leader_sequence[0]))) { +                if (leader_sequence_size < ARRAY_SIZE(leader_sequence)) {                      leader_sequence[leader_sequence_size] = keycode;                      leader_sequence_size++;                  } else { diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c index 6a8d8f0ff6..646471bc4d 100644 --- a/quantum/process_keycode/process_ucis.c +++ b/quantum/process_keycode/process_ucis.c @@ -15,6 +15,9 @@   */  #include "process_ucis.h" +#include "unicode.h" +#include "keycode.h" +#include "wait.h"  qk_ucis_state_t qk_ucis_state; @@ -26,9 +29,7 @@ void qk_ucis_start(void) {  }  __attribute__((weak)) void qk_ucis_start_user(void) { -    unicode_input_start(); -    register_hex(0x2328); // ⌨ -    unicode_input_finish(); +    register_unicode(0x2328); // ⌨  }  __attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {} @@ -51,10 +52,7 @@ static bool is_uni_seq(char *seq) {  __attribute__((weak)) void qk_ucis_symbol_fallback(void) {      for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) { -        uint8_t keycode = qk_ucis_state.codes[i]; -        register_code(keycode); -        unregister_code(keycode); -        wait_ms(UNICODE_TYPE_DELAY); +        tap_code(qk_ucis_state.codes[i]);      }  } @@ -63,7 +61,6 @@ __attribute__((weak)) void qk_ucis_cancel(void) {}  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);      }  } @@ -94,9 +91,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {          case KC_ENTER:          case KC_ESCAPE:              for (uint8_t i = 0; i < qk_ucis_state.count; i++) { -                register_code(KC_BACKSPACE); -                unregister_code(KC_BACKSPACE); -                wait_ms(UNICODE_TYPE_DELAY); +                tap_code(KC_BACKSPACE);              }              if (keycode == KC_ESCAPE) { diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h index a667430bda..3de0707762 100644 --- a/quantum/process_keycode/process_ucis.h +++ b/quantum/process_keycode/process_ucis.h @@ -16,8 +16,10 @@  #pragma once -#include "quantum.h" -#include "process_unicode_common.h" +#include <stdbool.h> +#include <stdint.h> + +#include "action.h"  #ifndef UCIS_MAX_SYMBOL_LENGTH  #    define UCIS_MAX_SYMBOL_LENGTH 32 diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c index 18a1d8bc1f..99cc2f5f26 100644 --- a/quantum/process_keycode/process_unicode.c +++ b/quantum/process_keycode/process_unicode.c @@ -15,14 +15,14 @@   */  #include "process_unicode.h" -#include "action_util.h" -#include "eeprom.h" +#include "unicode.h" +#include "quantum_keycodes.h"  bool process_unicode(uint16_t keycode, keyrecord_t *record) { -    if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX && record->event.pressed) { -        unicode_input_start(); -        register_hex(keycode & 0x7FFF); -        unicode_input_finish(); +    if (record->event.pressed) { +        if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX) { +            register_unicode(keycode & 0x7FFF); +        }      }      return true;  } diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h index 22765ad560..341bc8d861 100644 --- a/quantum/process_keycode/process_unicode.h +++ b/quantum/process_keycode/process_unicode.h @@ -16,6 +16,9 @@  #pragma once -#include "process_unicode_common.h" +#include <stdbool.h> +#include <stdint.h> + +#include "action.h"  bool process_unicode(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 8de31c055c..bd5fc560f3 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -15,289 +15,17 @@   */  #include "process_unicode_common.h" -#include "eeprom.h" -#include "utf8.h" +#include "unicode.h" +#include "action_util.h" +#include "keycode.h" -unicode_config_t unicode_config; -uint8_t          unicode_saved_mods; -bool             unicode_saved_caps_lock; -bool             unicode_saved_num_lock; - -#if UNICODE_SELECTED_MODES != -1 -static uint8_t selected[]     = {UNICODE_SELECTED_MODES}; -static int8_t  selected_count = sizeof selected / sizeof *selected; -static int8_t  selected_index; -#endif - -void unicode_input_mode_init(void) { -    unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE); -#if UNICODE_SELECTED_MODES != -1 -#    if UNICODE_CYCLE_PERSIST -    // Find input_mode in selected modes -    int8_t i; -    for (i = 0; i < selected_count; i++) { -        if (selected[i] == unicode_config.input_mode) { -            selected_index = i; -            break; -        } -    } -    if (i == selected_count) { -        // Not found: input_mode isn't selected, change to one that is -        unicode_config.input_mode = selected[selected_index = 0]; -    } -#    else -    // Always change to the first selected input mode -    unicode_config.input_mode = selected[selected_index = 0]; -#    endif -#endif -    dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode); -} - -uint8_t get_unicode_input_mode(void) { -    return unicode_config.input_mode; -} - -void set_unicode_input_mode(uint8_t mode) { -    unicode_config.input_mode = mode; -    persist_unicode_input_mode(); -    dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode); -} - -void cycle_unicode_input_mode(int8_t offset) { -#if UNICODE_SELECTED_MODES != -1 -    selected_index = (selected_index + offset) % selected_count; -    if (selected_index < 0) { -        selected_index += selected_count; -    } -    unicode_config.input_mode = selected[selected_index]; -#    if UNICODE_CYCLE_PERSIST -    persist_unicode_input_mode(); -#    endif -    dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode); -#endif -} - -void persist_unicode_input_mode(void) { -    eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); -} - -__attribute__((weak)) void unicode_input_start(void) { -    unicode_saved_caps_lock = host_keyboard_led_state().caps_lock; -    unicode_saved_num_lock  = host_keyboard_led_state().num_lock; - -    // Note the order matters here! -    // Need to do this before we mess around with the mods, or else -    // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work -    // correctly in the shifted case. -    if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) { -        tap_code(KC_CAPS_LOCK); -    } - -    unicode_saved_mods = get_mods(); // Save current mods -    clear_mods();                    // Unregister mods to start from a clean state -    clear_weak_mods(); - -    switch (unicode_config.input_mode) { -        case UC_MAC: -            register_code(UNICODE_KEY_MAC); -            break; -        case UC_LNX: -            tap_code16(UNICODE_KEY_LNX); -            break; -        case UC_WIN: -            // For increased reliability, use numpad keys for inputting digits -            if (!unicode_saved_num_lock) { -                tap_code(KC_NUM_LOCK); -            } -            register_code(KC_LEFT_ALT); -            wait_ms(UNICODE_TYPE_DELAY); -            tap_code(KC_KP_PLUS); -            break; -        case UC_WINC: -            tap_code(UNICODE_KEY_WINC); -            tap_code(KC_U); -            break; -        case UC_EMACS: -            // The usual way to type unicode in emacs is C-x-8 <RET> then the unicode number in hex -            tap_code16(LCTL(KC_X)); -            tap_code16(KC_8); -            tap_code16(KC_ENTER); -            break; -    } - -    wait_ms(UNICODE_TYPE_DELAY); -} - -__attribute__((weak)) void unicode_input_finish(void) { -    switch (unicode_config.input_mode) { -        case UC_MAC: -            unregister_code(UNICODE_KEY_MAC); -            break; -        case UC_LNX: -            tap_code(KC_SPACE); -            if (unicode_saved_caps_lock) { -                tap_code(KC_CAPS_LOCK); -            } -            break; -        case UC_WIN: -            unregister_code(KC_LEFT_ALT); -            if (!unicode_saved_num_lock) { -                tap_code(KC_NUM_LOCK); -            } -            break; -        case UC_WINC: -            tap_code(KC_ENTER); -            break; -        case UC_EMACS: -            tap_code16(KC_ENTER); -            break; -    } - -    set_mods(unicode_saved_mods); // Reregister previously set mods -} - -__attribute__((weak)) void unicode_input_cancel(void) { -    switch (unicode_config.input_mode) { -        case UC_MAC: -            unregister_code(UNICODE_KEY_MAC); -            break; -        case UC_LNX: -            tap_code(KC_ESCAPE); -            if (unicode_saved_caps_lock) { -                tap_code(KC_CAPS_LOCK); -            } -            break; -        case UC_WINC: -            tap_code(KC_ESCAPE); -            break; -        case UC_WIN: -            unregister_code(KC_LEFT_ALT); -            if (!unicode_saved_num_lock) { -                tap_code(KC_NUM_LOCK); -            } -            break; -        case UC_EMACS: -            tap_code16(LCTL(KC_G)); // C-g cancels -            break; -    } - -    set_mods(unicode_saved_mods); // Reregister previously set mods -} - -// clang-format off - -static void send_nibble_wrapper(uint8_t digit) { -    if (unicode_config.input_mode == UC_WIN) { -        uint8_t kc = digit < 10 -                   ? KC_KP_1 + (10 + digit - 1) % 10 -                   : KC_A + (digit - 10); -        tap_code(kc); -        return; -    } -    send_nibble(digit); -} - -// clang-format on - -void register_hex(uint16_t hex) { -    for (int i = 3; i >= 0; i--) { -        uint8_t digit = ((hex >> (i * 4)) & 0xF); -        send_nibble_wrapper(digit); -    } -} - -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) { -                send_nibble_wrapper(digit); -            } -        } else { -            send_nibble_wrapper(digit); -            onzerostart = false; -        } -    } -} - -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(); -} - -void send_unicode_string(const char *str) { -    if (!str) { -        return; -    } - -    while (*str) { -        int32_t code_point = 0; -        str                = decode_utf8(str, &code_point); - -        if (code_point >= 0) { -            register_unicode(code_point); -        } -    } -} - -// clang-format off - -static void audio_helper(void) { -#ifdef AUDIO_ENABLE -    switch (get_unicode_input_mode()) { -#    ifdef UNICODE_SONG_MAC -        static float song_mac[][2] = UNICODE_SONG_MAC; -        case UC_MAC: -            PLAY_SONG(song_mac); -            break; -#    endif -#    ifdef UNICODE_SONG_LNX -        static float song_lnx[][2] = UNICODE_SONG_LNX; -        case UC_LNX: -            PLAY_SONG(song_lnx); -            break; -#    endif -#    ifdef UNICODE_SONG_WIN -        static float song_win[][2] = UNICODE_SONG_WIN; -        case UC_WIN: -            PLAY_SONG(song_win); -            break; -#    endif -#    ifdef UNICODE_SONG_BSD -        static float song_bsd[][2] = UNICODE_SONG_BSD; -        case UC_BSD: -            PLAY_SONG(song_bsd); -            break; -#    endif -#    ifdef UNICODE_SONG_WINC -        static float song_winc[][2] = UNICODE_SONG_WINC; -        case UC_WINC: -            PLAY_SONG(song_winc); -            break; -#    endif -    } +#if defined(UNICODE_ENABLE) +#    include "process_unicode.h" +#elif defined(UNICODEMAP_ENABLE) +#    include "process_unicodemap.h" +#elif defined(UCIS_ENABLE) +#    include "process_ucis.h"  #endif -} - -// clang-format on  bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {      if (record->event.pressed) { @@ -305,35 +33,27 @@ bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {          switch (keycode) {              case UNICODE_MODE_FORWARD:                  cycle_unicode_input_mode(shifted ? -1 : +1); -                audio_helper();                  break;              case UNICODE_MODE_REVERSE:                  cycle_unicode_input_mode(shifted ? +1 : -1); -                audio_helper();                  break;              case UNICODE_MODE_MAC:                  set_unicode_input_mode(UC_MAC); -                audio_helper();                  break;              case UNICODE_MODE_LNX:                  set_unicode_input_mode(UC_LNX); -                audio_helper();                  break;              case UNICODE_MODE_WIN:                  set_unicode_input_mode(UC_WIN); -                audio_helper();                  break;              case UNICODE_MODE_BSD:                  set_unicode_input_mode(UC_BSD); -                audio_helper();                  break;              case UNICODE_MODE_WINC:                  set_unicode_input_mode(UC_WINC); -                audio_helper();                  break;              case UNICODE_MODE_EMACS:                  set_unicode_input_mode(UC_EMACS); -                audio_helper();                  break;          }      } diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h index 15e798dbb3..fd09a41818 100644 --- a/quantum/process_keycode/process_unicode_common.h +++ b/quantum/process_keycode/process_unicode_common.h @@ -16,187 +16,9 @@  #pragma once -#include "quantum.h" +#include <stdbool.h> +#include <stdint.h> -#if defined(UNICODE_ENABLE) + defined(UNICODEMAP_ENABLE) + defined(UCIS_ENABLE) > 1 -#    error "Cannot enable more than one Unicode method (UNICODE, UNICODEMAP, UCIS) at the same time" -#endif - -// Keycodes used for starting Unicode input on different platforms -#ifndef UNICODE_KEY_MAC -#    define UNICODE_KEY_MAC KC_LEFT_ALT -#endif -#ifndef UNICODE_KEY_LNX -#    define UNICODE_KEY_LNX LCTL(LSFT(KC_U)) -#endif -#ifndef UNICODE_KEY_WINC -#    define UNICODE_KEY_WINC KC_RIGHT_ALT -#endif - -// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle) -// Example: #define UNICODE_SELECTED_MODES UC_WINC, UC_LNX -#ifndef UNICODE_SELECTED_MODES -#    define UNICODE_SELECTED_MODES -1 -#endif - -// Whether input mode changes in cycle should be written to EEPROM -#ifndef UNICODE_CYCLE_PERSIST -#    define UNICODE_CYCLE_PERSIST true -#endif - -// Delay between starting Unicode input and sending a sequence, in ms -#ifndef UNICODE_TYPE_DELAY -#    define UNICODE_TYPE_DELAY 10 -#endif - -// Deprecated aliases -#if !defined(UNICODE_KEY_MAC) && defined(UNICODE_KEY_OSX) -#    define UNICODE_KEY_MAC UNICODE_KEY_OSX -#endif -#if !defined(UNICODE_SONG_MAC) && defined(UNICODE_SONG_OSX) -#    define UNICODE_SONG_MAC UNICODE_SONG_OSX -#endif -#define UC_OSX UC_MAC - -enum unicode_input_modes { -    UC_MAC,   // macOS using Unicode Hex Input -    UC_LNX,   // Linux using IBus -    UC_WIN,   // Windows using EnableHexNumpad -    UC_BSD,   // BSD (not implemented) -    UC_WINC,  // Windows using WinCompose (https://github.com/samhocevar/wincompose) -    UC_EMACS, // Emacs is an operating system in search of a good text editor -    UC__COUNT // Number of available input modes (always leave at the end) -}; - -typedef union { -    uint32_t raw; -    struct { -        uint8_t input_mode : 8; -    }; -} unicode_config_t; - -extern unicode_config_t unicode_config; - -void    unicode_input_mode_init(void); -uint8_t get_unicode_input_mode(void); -void    set_unicode_input_mode(uint8_t mode); -void    cycle_unicode_input_mode(int8_t offset); -void    persist_unicode_input_mode(void); - -void unicode_input_start(void); -void unicode_input_finish(void); -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_string(const char *str); +#include "action.h"  bool process_unicode_common(uint16_t keycode, keyrecord_t *record); - -#define UC_BSPC UC(0x0008) -#define UC_SPC UC(0x0020) - -#define UC_EXLM UC(0x0021) -#define UC_DQUT UC(0x0022) -#define UC_HASH UC(0x0023) -#define UC_DLR UC(0x0024) -#define UC_PERC UC(0x0025) -#define UC_AMPR UC(0x0026) -#define UC_QUOT UC(0x0027) -#define UC_LPRN UC(0x0028) -#define UC_RPRN UC(0x0029) -#define UC_ASTR UC(0x002A) -#define UC_PLUS UC(0x002B) -#define UC_COMM UC(0x002C) -#define UC_DASH UC(0x002D) -#define UC_DOT UC(0x002E) -#define UC_SLSH UC(0x002F) - -#define UC_0 UC(0x0030) -#define UC_1 UC(0x0031) -#define UC_2 UC(0x0032) -#define UC_3 UC(0x0033) -#define UC_4 UC(0x0034) -#define UC_5 UC(0x0035) -#define UC_6 UC(0x0036) -#define UC_7 UC(0x0037) -#define UC_8 UC(0x0038) -#define UC_9 UC(0x0039) - -#define UC_COLN UC(0x003A) -#define UC_SCLN UC(0x003B) -#define UC_LT UC(0x003C) -#define UC_EQL UC(0x003D) -#define UC_GT UC(0x003E) -#define UC_QUES UC(0x003F) -#define UC_AT UC(0x0040) - -#define UC_A UC(0x0041) -#define UC_B UC(0x0042) -#define UC_C UC(0x0043) -#define UC_D UC(0x0044) -#define UC_E UC(0x0045) -#define UC_F UC(0x0046) -#define UC_G UC(0x0047) -#define UC_H UC(0x0048) -#define UC_I UC(0x0049) -#define UC_J UC(0x004A) -#define UC_K UC(0x004B) -#define UC_L UC(0x004C) -#define UC_M UC(0x004D) -#define UC_N UC(0x004E) -#define UC_O UC(0x004F) -#define UC_P UC(0x0050) -#define UC_Q UC(0x0051) -#define UC_R UC(0x0052) -#define UC_S UC(0x0053) -#define UC_T UC(0x0054) -#define UC_U UC(0x0055) -#define UC_V UC(0x0056) -#define UC_W UC(0x0057) -#define UC_X UC(0x0058) -#define UC_Y UC(0x0059) -#define UC_Z UC(0x005A) - -#define UC_LBRC UC(0x005B) -#define UC_BSLS UC(0x005C) -#define UC_RBRC UC(0x005D) -#define UC_CIRM UC(0x005E) -#define UC_UNDR UC(0x005F) - -#define UC_GRV UC(0x0060) - -#define UC_a UC(0x0061) -#define UC_b UC(0x0062) -#define UC_c UC(0x0063) -#define UC_d UC(0x0064) -#define UC_e UC(0x0065) -#define UC_f UC(0x0066) -#define UC_g UC(0x0067) -#define UC_h UC(0x0068) -#define UC_i UC(0x0069) -#define UC_j UC(0x006A) -#define UC_k UC(0x006B) -#define UC_l UC(0x006C) -#define UC_m UC(0x006D) -#define UC_n UC(0x006E) -#define UC_o UC(0x006F) -#define UC_p UC(0x0070) -#define UC_q UC(0x0071) -#define UC_r UC(0x0072) -#define UC_s UC(0x0073) -#define UC_t UC(0x0074) -#define UC_u UC(0x0075) -#define UC_v UC(0x0076) -#define UC_w UC(0x0077) -#define UC_x UC(0x0078) -#define UC_y UC(0x0079) -#define UC_z UC(0x007A) - -#define UC_LCBR UC(0x007B) -#define UC_PIPE UC(0x007C) -#define UC_RCBR UC(0x007D) -#define UC_TILD UC(0x007E) -#define UC_DEL UC(0x007F) diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c index 459397014d..979d773b05 100644 --- a/quantum/process_keycode/process_unicodemap.c +++ b/quantum/process_keycode/process_unicodemap.c @@ -15,6 +15,11 @@   */  #include "process_unicodemap.h" +#include "unicode.h" +#include "quantum_keycodes.h" +#include "keycode.h" +#include "action_util.h" +#include "host.h"  __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {      if (keycode >= QK_UNICODEMAP_PAIR) { diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h index c429859bbb..73f5449864 100644 --- a/quantum/process_keycode/process_unicodemap.h +++ b/quantum/process_keycode/process_unicodemap.h @@ -16,7 +16,11 @@  #pragma once -#include "process_unicode_common.h" +#include <stdbool.h> +#include <stdint.h> + +#include "action.h" +#include "progmem.h"  extern const uint32_t PROGMEM unicode_map[]; | 
