From 3fa592a4024a24a636fa0c562e6761667a94f565 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Tue, 14 Dec 2021 20:53:36 -0800 Subject: [Keymap] Unicode and Pointing Device and Autocorect for drashna keymaps (#15415) --- .../keyrecords/autocorrection/autocorrection.c | 143 +++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 users/drashna/keyrecords/autocorrection/autocorrection.c (limited to 'users/drashna/keyrecords/autocorrection/autocorrection.c') diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c new file mode 100644 index 0000000000..7c8c28c674 --- /dev/null +++ b/users/drashna/keyrecords/autocorrection/autocorrection.c @@ -0,0 +1,143 @@ +// Copyright 2021 Google LLC +// Copyright 2022 @filterpaper +// SPDX-License-Identifier: Apache-2.0 +// Original source: https://getreuer.info/posts/keyboards/autocorrection + +#include "autocorrection.h" +#include + +#if __has_include("autocorrection_data.h") +# include "autocorrection_data.h" +# if AUTOCORRECTION_MIN_LENGTH < 4 +# error Minimum Length is too short and may cause overflows +# endif + +bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { + static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC}; + static uint8_t typo_buffer_size = 1; + + if (keycode == AUTO_CTN) { + if (record->event.pressed) { + typo_buffer_size = 0; + userspace_config.autocorrection ^= 1; + eeconfig_update_user(userspace_config.raw); + } + return false; + } + + if (!userspace_config.autocorrection) { + typo_buffer_size = 0; + return true; + } + + switch (keycode) { + case KC_LSFT: + case KC_RSFT: + return true; +# ifndef NO_ACTION_TAPPING + case QK_MOD_TAP ... QK_MOD_TAP_MAX: + if (((keycode >> 8) & 0xF) == MOD_LSFT) { + return true; + } +# ifndef NO_ACTION_LAYER + case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: +# endif + if (record->event.pressed || !record->tap.count) { + return true; + } + keycode &= 0xFF; + break; +# endif +# ifndef NO_ACTION_ONESHOT + case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: + if ((keycode & 0xF) == MOD_LSFT) { + return true; + } +# endif + default: + if (!record->event.pressed) { + return true; + } + } + + // Subtract buffer for Backspace key, reset for other non-alpha. + if (!(KC_A <= keycode && keycode <= KC_Z)) { + if (keycode == KC_BSPC) { + // Remove last character from the buffer. + if (typo_buffer_size > 0) { + --typo_buffer_size; + } + return true; + } else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) { + // Set a word boundary if space, period, digit, etc. is pressed. + // Behave more conservatively for the enter key. Reset, so that enter + // can't be used on a word ending. + if (keycode == KC_ENT) { + typo_buffer_size = 0; + } + keycode = KC_SPC; + } else { + // 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 >= AUTOCORRECTION_MAX_LENGTH) { + memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1); + typo_buffer_size = AUTOCORRECTION_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 < AUTOCORRECTION_MIN_LENGTH) { + return true; + } + + // Check for typo in buffer using a trie stored in `autocorrection_data`. + uint16_t state = 0; + uint8_t code = pgm_read_byte(autocorrection_data + state); + for (uint8_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(autocorrection_data + (state += 3))) { + if (!code) return true; + } + // Follow link to child node. + state = (pgm_read_byte(autocorrection_data + state + 1) | pgm_read_byte(autocorrection_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(autocorrection_data + (++state)))) { + ++state; + } + + code = pgm_read_byte(autocorrection_data + state); + + if (code & 128) { // A typo was found! Apply autocorrection. + const uint8_t backspaces = code & 63; + for (uint8_t i = 0; i < backspaces; ++i) { + tap_code(KC_BSPC); + } + send_string_P((char const*)(autocorrection_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; +} +#else +# pragma message "Warning!!! Autocorrect is not corretly setup!" +bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; } +#endif -- cgit v1.2.3