summaryrefslogtreecommitdiffstats
path: root/users/drashna/keyrecords/autocorrection/autocorrection.c
diff options
context:
space:
mode:
Diffstat (limited to 'users/drashna/keyrecords/autocorrection/autocorrection.c')
-rw-r--r--users/drashna/keyrecords/autocorrection/autocorrection.c143
1 files changed, 143 insertions, 0 deletions
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 <string.h>
+
+#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