summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2022-09-17 00:50:54 -0700
committerGitHub <noreply@github.com>2022-09-17 17:50:54 +1000
commitfb29c0ae53e32fb049516fcbe0f7863882ca9173 (patch)
tree989feaa47190248726a462bf761a98f46d91f406 /quantum
parentd67d388e776eeb8596181894639b6ed46c8a2d7d (diff)
[Core] Add getreuer's Autocorrect feature to core (#15699)
Co-authored-by: Albert Y <76888457+filterpaper@users.noreply.github.com>
Diffstat (limited to 'quantum')
-rw-r--r--quantum/eeconfig.c2
-rw-r--r--quantum/keycode_config.h1
-rw-r--r--quantum/process_keycode/autocorrect_data_default.h85
-rw-r--r--quantum/process_keycode/process_autocorrect.c287
-rw-r--r--quantum/process_keycode/process_autocorrect.h17
-rw-r--r--quantum/quantum.c3
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/quantum_keycodes.h8
8 files changed, 406 insertions, 1 deletions
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index 0b7ae39907..7c0431fd12 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -46,7 +46,7 @@ void eeconfig_init_quantum(void) {
46 eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0); 46 eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
47 default_layer_state = 0; 47 default_layer_state = 0;
48 eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, 0); 48 eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, 0);
49 eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 0x4); 49 eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 0xC);
50 eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0); 50 eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
51 eeprom_update_byte(EECONFIG_BACKLIGHT, 0); 51 eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
52 eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default 52 eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
index 81a8e61471..eef048d95c 100644
--- a/quantum/keycode_config.h
+++ b/quantum/keycode_config.h
@@ -39,6 +39,7 @@ typedef union {
39 bool swap_rctl_rgui : 1; 39 bool swap_rctl_rgui : 1;
40 bool oneshot_enable : 1; 40 bool oneshot_enable : 1;
41 bool swap_escape_capslock : 1; 41 bool swap_escape_capslock : 1;
42 bool autocorrect_enable : 1;
42 }; 43 };
43} keymap_config_t; 44} keymap_config_t;
44 45
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 @@
1// Generated code.
2
3// Autocorrection dictionary (70 entries):
4// :guage -> gauge
5// :the:the: -> the
6// :thier -> their
7// :ture -> true
8// accomodate -> accommodate
9// acommodate -> accommodate
10// aparent -> apparent
11// aparrent -> apparent
12// apparant -> apparent
13// apparrent -> apparent
14// aquire -> acquire
15// becuase -> because
16// cauhgt -> caught
17// cheif -> chief
18// choosen -> chosen
19// cieling -> ceiling
20// collegue -> colleague
21// concensus -> consensus
22// contians -> contains
23// cosnt -> const
24// dervied -> derived
25// fales -> false
26// fasle -> false
27// fitler -> filter
28// flase -> false
29// foward -> forward
30// frequecy -> frequency
31// gaurantee -> guarantee
32// guaratee -> guarantee
33// heigth -> height
34// heirarchy -> hierarchy
35// inclued -> include
36// interator -> iterator
37// intput -> input
38// invliad -> invalid
39// lenght -> length
40// liasion -> liaison
41// libary -> library
42// listner -> listener
43// looses: -> loses
44// looup -> lookup
45// manefist -> manifest
46// namesapce -> namespace
47// namespcae -> namespace
48// occassion -> occasion
49// occured -> occurred
50// ouptut -> output
51// ouput -> output
52// overide -> override
53// postion -> position
54// priviledge -> privilege
55// psuedo -> pseudo
56// recieve -> receive
57// refered -> referred
58// relevent -> relevant
59// repitition -> repetition
60// retrun -> return
61// retun -> return
62// reuslt -> result
63// reutrn -> return
64// saftey -> safety
65// seperate -> separate
66// singed -> signed
67// stirng -> string
68// strign -> string
69// swithc -> switch
70// swtich -> switch
71// thresold -> threshold
72// udpate -> update
73// widht -> width
74
75#define AUTOCORRECT_MIN_LENGTH 5 // ":ture"
76#define AUTOCORRECT_MAX_LENGTH 10 // "accomodate"
77
78#define DICTIONARY_SIZE 1104
79
80static 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,
81 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,
82 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,
83 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,
84 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,
85 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 @@
1// Copyright 2021 Google LLC
2// Copyright 2021 @filterpaper
3// SPDX-License-Identifier: Apache-2.0
4// Original source: https://getreuer.info/posts/keyboards/autocorrection
5
6#include "process_autocorrect.h"
7#include <string.h>
8#include "keycode_config.h"
9
10#if __has_include("autocorrect_data.h")
11# include "autocorrect_data.h"
12#else
13# pragma message "Autocorrect is using the default library."
14# include "autocorrect_data_default.h"
15#endif
16
17static uint8_t typo_buffer[AUTOCORRECT_MAX_LENGTH] = {KC_SPC};
18static uint8_t typo_buffer_size = 1;
19
20/**
21 * @brief function for querying the enabled state of autocorrect
22 *
23 * @return true if enabled
24 * @return false if disabled
25 */
26bool autocorrect_is_enabled(void) {
27 return keymap_config.autocorrect_enable;
28}
29
30/**
31 * @brief Enables autocorrect and saves state to eeprom
32 *
33 */
34void autocorrect_enable(void) {
35 keymap_config.autocorrect_enable = true;
36 eeconfig_update_keymap(keymap_config.raw);
37}
38
39/**
40 * @brief Disables autocorrect and saves state to eeprom
41 *
42 */
43void autocorrect_disable(void) {
44 keymap_config.autocorrect_enable = false;
45 typo_buffer_size = 0;
46 eeconfig_update_keymap(keymap_config.raw);
47}
48
49/**
50 * @brief Toggles autocorrect's status and save state to eeprom
51 *
52 */
53void autocorrect_toggle(void) {
54 keymap_config.autocorrect_enable = !keymap_config.autocorrect_enable;
55 typo_buffer_size = 0;
56 eeconfig_update_keymap(keymap_config.raw);
57}
58
59/**
60 * @brief handler for determining if autocorrect should process keypress
61 *
62 * @param keycode Keycode registered by matrix press, per keymap
63 * @param record keyrecord_t structure
64 * @param typo_buffer_size passed along to allow resetting of autocorrect buffer
65 * @param mods allow processing of mod status
66 * @return true Allow autocorection
67 * @return false Stop processing and escape from autocorrect.
68 */
69__attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) {
70 // See quantum_keycodes.h for reference on these matched ranges.
71 switch (*keycode) {
72 // Exclude these keycodes from processing.
73 case KC_LSFT:
74 case KC_RSFT:
75 case KC_CAPS:
76 case QK_TO ... QK_ONE_SHOT_LAYER_MAX:
77 case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX:
78 case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
79 return false;
80
81 // Mask for base keycode from shifted keys.
82 case QK_LSFT ... QK_LSFT + 255:
83 case QK_RSFT ... QK_RSFT + 255:
84 if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) {
85 *mods |= MOD_LSFT;
86 } else {
87 *mods |= MOD_RSFT;
88 }
89 *keycode &= 0xFF; // Get the basic keycode.
90 return true;
91#ifndef NO_ACTION_TAPPING
92 // Exclude tap-hold keys when they are held down
93 // and mask for base keycode when they are tapped.
94 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
95# ifdef NO_ACTION_LAYER
96 // Exclude Layer Tap, if layers are disabled
97 // but action tapping is still enabled.
98 return false;
99# endif
100 case QK_MOD_TAP ... QK_MOD_TAP_MAX:
101 // Exclude hold keycode
102 if (!record->tap.count) {
103 return false;
104 }
105 *keycode &= 0xFF;
106 break;
107#else
108 case QK_MOD_TAP ... QK_MOD_TAP_MAX:
109 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
110 // Exclude if disabled
111 return false;
112#endif
113 // Exclude swap hands keys when they are held down
114 // and mask for base keycode when they are tapped.
115 case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
116#ifdef SWAP_HANDS_ENABLE
117 if (*keycode >= 0x56F0 || !record->tap.count) {
118 return false;
119 }
120 *keycode &= 0xFF;
121 break;
122#else
123 // Exclude if disabled
124 return false;
125#endif
126 }
127
128 // Disable autocorrect while a mod other than shift is active.
129 if ((*mods & ~MOD_MASK_SHIFT) != 0) {
130 *typo_buffer_size = 0;
131 return false;
132 }
133
134 return true;
135}
136
137/**
138 * @brief handling for when autocorrection has been triggered
139 *
140 * @param backspaces number of characters to remove
141 * @param str pointer to PROGMEM string to replace mistyped seletion with
142 * @return true apply correction
143 * @return false user handled replacement
144 */
145__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) {
146 return true;
147}
148
149/**
150 * @brief Process handler for autocorrect feature
151 *
152 * @param keycode Keycode registered by matrix press, per keymap
153 * @param record keyrecord_t structure
154 * @return true Continue processing keycodes, and send to host
155 * @return false Stop processing keycodes, and don't send to host
156 */
157bool process_autocorrect(uint16_t keycode, keyrecord_t *record) {
158 uint8_t mods = get_mods();
159#ifndef NO_ACTION_ONESHOT
160 mods |= get_oneshot_mods();
161#endif
162
163 if ((keycode >= AUTOCORRECT_ON && keycode <= AUTOCORRECT_TOGGLE) && record->event.pressed) {
164 if (keycode == AUTOCORRECT_ON) {
165 autocorrect_enable();
166 } else if (keycode == AUTOCORRECT_OFF) {
167 autocorrect_disable();
168 } else if (keycode == AUTOCORRECT_TOGGLE) {
169 autocorrect_toggle();
170 } else {
171 return true;
172 }
173
174 return false;
175 }
176
177 if (!keymap_config.autocorrect_enable) {
178 typo_buffer_size = 0;
179 return true;
180 }
181
182 if (!record->event.pressed) {
183 return true;
184 }
185
186 // autocorrect keycode verification and extraction
187 if (!process_autocorrect_user(&keycode, record, &typo_buffer_size, &mods)) {
188 return true;
189 }
190
191 // keycode buffer check
192 switch (keycode) {
193 case KC_A ... KC_Z:
194 // process normally
195 break;
196 case KC_1 ... KC_0:
197 case KC_TAB ... KC_SEMICOLON:
198 case KC_GRAVE ... KC_SLASH:
199 // Set a word boundary if space, period, digit, etc. is pressed.
200 keycode = KC_SPC;
201 break;
202 case KC_ENTER:
203 // Behave more conservatively for the enter key. Reset, so that enter
204 // can't be used on a word ending.
205 typo_buffer_size = 0;
206 keycode = KC_SPC;
207 break;
208 case KC_BSPC:
209 // Remove last character from the buffer.
210 if (typo_buffer_size > 0) {
211 --typo_buffer_size;
212 }
213 return true;
214 case KC_QUOTE:
215 // Treat " (shifted ') as a word boundary.
216 if ((mods & MOD_MASK_SHIFT) != 0) {
217 keycode = KC_SPC;
218 }
219 break;
220 default:
221 // Clear state if some other non-alpha key is pressed.
222 typo_buffer_size = 0;
223 return true;
224 }
225
226 // Rotate oldest character if buffer is full.
227 if (typo_buffer_size >= AUTOCORRECT_MAX_LENGTH) {
228 memmove(typo_buffer, typo_buffer + 1, AUTOCORRECT_MAX_LENGTH - 1);
229 typo_buffer_size = AUTOCORRECT_MAX_LENGTH - 1;
230 }
231
232 // Append `keycode` to buffer.
233 typo_buffer[typo_buffer_size++] = keycode;
234 // Return if buffer is smaller than the shortest word.
235 if (typo_buffer_size < AUTOCORRECT_MIN_LENGTH) {
236 return true;
237 }
238
239 // Check for typo in buffer using a trie stored in `autocorrect_data`.
240 uint16_t state = 0;
241 uint8_t code = pgm_read_byte(autocorrect_data + state);
242 for (int8_t i = typo_buffer_size - 1; i >= 0; --i) {
243 uint8_t const key_i = typo_buffer[i];
244
245 if (code & 64) { // Check for match in node with multiple children.
246 code &= 63;
247 for (; code != key_i; code = pgm_read_byte(autocorrect_data + (state += 3))) {
248 if (!code) return true;
249 }
250 // Follow link to child node.
251 state = (pgm_read_byte(autocorrect_data + state + 1) | pgm_read_byte(autocorrect_data + state + 2) << 8);
252 // Check for match in node with single child.
253 } else if (code != key_i) {
254 return true;
255 } else if (!(code = pgm_read_byte(autocorrect_data + (++state)))) {
256 ++state;
257 }
258
259 // Stop if `state` becomes an invalid index. This should not normally
260 // happen, it is a safeguard in case of a bug, data corruption, etc.
261 if (state >= DICTIONARY_SIZE) {
262 return true;
263 }
264
265 code = pgm_read_byte(autocorrect_data + state);
266
267 if (code & 128) { // A typo was found! Apply autocorrect.
268 const uint8_t backspaces = (code & 63) + !record->event.pressed;
269 if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) {
270 for (uint8_t i = 0; i < backspaces; ++i) {
271 tap_code(KC_BSPC);
272 }
273 send_string_P((char const *)(autocorrect_data + state + 1));
274 }
275
276 if (keycode == KC_SPC) {
277 typo_buffer[0] = KC_SPC;
278 typo_buffer_size = 1;
279 return true;
280 } else {
281 typo_buffer_size = 0;
282 return false;
283 }
284 }
285 }
286 return true;
287}
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 @@
1// Copyright 2021 Google LLC
2// Copyright 2021 @filterpaper
3// SPDX-License-Identifier: Apache-2.0
4// Original source: https://getreuer.info/posts/keyboards/autocorrection
5
6#pragma once
7
8#include "quantum.h"
9
10bool process_autocorrect(uint16_t keycode, keyrecord_t *record);
11bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
12bool apply_autocorrect(uint8_t backspaces, const char *str);
13
14bool autocorrect_is_enabled(void);
15void autocorrect_enable(void);
16void autocorrect_disable(void);
17void autocorrect_toggle(void);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index acafd8025c..9f1d3502fb 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -336,6 +336,9 @@ bool process_record_quantum(keyrecord_t *record) {
336#ifdef PROGRAMMABLE_BUTTON_ENABLE 336#ifdef PROGRAMMABLE_BUTTON_ENABLE
337 process_programmable_button(keycode, record) && 337 process_programmable_button(keycode, record) &&
338#endif 338#endif
339#ifdef AUTOCORRECT_ENABLE
340 process_autocorrect(keycode, record) &&
341#endif
339 true)) { 342 true)) {
340 return false; 343 return false;
341 } 344 }
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 51360c3d2a..9c1b9952b8 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -236,6 +236,10 @@ extern layer_state_t layer_state;
236# include "process_caps_word.h" 236# include "process_caps_word.h"
237#endif 237#endif
238 238
239#ifdef AUTOCORRECT_ENABLE
240# include "process_autocorrect.h"
241#endif
242
239// For tri-layer 243// For tri-layer
240void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3); 244void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
241layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3); 245layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index c8f03fa1ce..abf3f1a384 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -611,6 +611,10 @@ enum quantum_keycodes {
611 611
612 UNICODE_MODE_EMACS, 612 UNICODE_MODE_EMACS,
613 613
614 AUTOCORRECT_ON,
615 AUTOCORRECT_OFF,
616 AUTOCORRECT_TOGGLE,
617
614 // Start of custom keycode range for keyboards and keymaps - always leave at the end 618 // Start of custom keycode range for keyboards and keymaps - always leave at the end
615 SAFE_RANGE 619 SAFE_RANGE
616}; 620};
@@ -799,6 +803,10 @@ enum quantum_keycodes {
799#define EH_LEFT MAGIC_EE_HANDS_LEFT 803#define EH_LEFT MAGIC_EE_HANDS_LEFT
800#define EH_RGHT MAGIC_EE_HANDS_RIGHT 804#define EH_RGHT MAGIC_EE_HANDS_RIGHT
801 805
806#define CRT_ON AUTOCORRECT_ON
807#define CRT_OFF AUTOCORRECT_OFF
808#define CRT_TOG AUTOCORRECT_TOGGLE
809
802// GOTO layer - 256 layer max 810// GOTO layer - 256 layer max
803#define TO(layer) (QK_TO | ((layer)&0xFF)) 811#define TO(layer) (QK_TO | ((layer)&0xFF))
804 812