aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode/process_unicode.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode/process_unicode.c')
-rw-r--r--quantum/process_keycode/process_unicode.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
new file mode 100644
index 000000000..cd3a610b4
--- /dev/null
+++ b/quantum/process_keycode/process_unicode.c
@@ -0,0 +1,264 @@
1#include "process_unicode.h"
2
3static uint8_t input_mode;
4
5__attribute__((weak))
6uint16_t hex_to_keycode(uint8_t hex)
7{
8 if (hex == 0x0) {
9 return KC_0;
10 } else if (hex < 0xA) {
11 return KC_1 + (hex - 0x1);
12 } else {
13 return KC_A + (hex - 0xA);
14 }
15}
16
17void set_unicode_input_mode(uint8_t os_target)
18{
19 input_mode = os_target;
20}
21
22uint8_t get_unicode_input_mode(void) {
23 return input_mode;
24}
25
26__attribute__((weak))
27void unicode_input_start (void) {
28 switch(input_mode) {
29 case UC_OSX:
30 register_code(KC_LALT);
31 break;
32 case UC_LNX:
33 register_code(KC_LCTL);
34 register_code(KC_LSFT);
35 register_code(KC_U);
36 unregister_code(KC_U);
37 unregister_code(KC_LSFT);
38 unregister_code(KC_LCTL);
39 break;
40 case UC_WIN:
41 register_code(KC_LALT);
42 register_code(KC_PPLS);
43 unregister_code(KC_PPLS);
44 break;
45 case UC_WINC:
46 register_code(KC_RALT);
47 unregister_code(KC_RALT);
48 register_code(KC_U);
49 unregister_code(KC_U);
50 }
51 wait_ms(UNICODE_TYPE_DELAY);
52}
53
54__attribute__((weak))
55void unicode_input_finish (void) {
56 switch(input_mode) {
57 case UC_OSX:
58 case UC_WIN:
59 unregister_code(KC_LALT);
60 break;
61 case UC_LNX:
62 register_code(KC_SPC);
63 unregister_code(KC_SPC);
64 break;
65 }
66}
67
68void register_hex(uint16_t hex) {
69 for(int i = 3; i >= 0; i--) {
70 uint8_t digit = ((hex >> (i*4)) & 0xF);
71 register_code(hex_to_keycode(digit));
72 unregister_code(hex_to_keycode(digit));
73 }
74}
75
76bool process_unicode(uint16_t keycode, keyrecord_t *record) {
77 if (keycode > QK_UNICODE && record->event.pressed) {
78 uint16_t unicode = keycode & 0x7FFF;
79 unicode_input_start();
80 register_hex(unicode);
81 unicode_input_finish();
82 }
83 return true;
84}
85
86#ifdef UNICODEMAP_ENABLE
87__attribute__((weak))
88const uint32_t PROGMEM unicode_map[] = {
89};
90
91void register_hex32(uint32_t hex) {
92 uint8_t onzerostart = 1;
93 for(int i = 7; i >= 0; i--) {
94 if (i <= 3) {
95 onzerostart = 0;
96 }
97 uint8_t digit = ((hex >> (i*4)) & 0xF);
98 if (digit == 0) {
99 if (onzerostart == 0) {
100 register_code(hex_to_keycode(digit));
101 unregister_code(hex_to_keycode(digit));
102 }
103 } else {
104 register_code(hex_to_keycode(digit));
105 unregister_code(hex_to_keycode(digit));
106 onzerostart = 0;
107 }
108 }
109}
110
111__attribute__((weak))
112void unicode_map_input_error() {}
113
114bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
115 if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
116 const uint32_t* map = unicode_map;
117 uint16_t index = keycode & 0x7FF;
118 uint32_t code = pgm_read_dword_far(&map[index]);
119 if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
120 // when character is out of range supported by the OS
121 unicode_map_input_error();
122 } else {
123 unicode_input_start();
124 register_hex32(code);
125 unicode_input_finish();
126 }
127 }
128 return true;
129}
130#endif
131
132#ifdef UCIS_ENABLE
133qk_ucis_state_t qk_ucis_state;
134
135void qk_ucis_start(void) {
136 qk_ucis_state.count = 0;
137 qk_ucis_state.in_progress = true;
138
139 qk_ucis_start_user();
140}
141
142__attribute__((weak))
143void qk_ucis_start_user(void) {
144 unicode_input_start();
145 register_hex(0x2328);
146 unicode_input_finish();
147}
148
149static bool is_uni_seq(char *seq) {
150 uint8_t i;
151
152 for (i = 0; seq[i]; i++) {
153 uint16_t code;
154 if (('1' <= seq[i]) && (seq[i] <= '0'))
155 code = seq[i] - '1' + KC_1;
156 else
157 code = seq[i] - 'a' + KC_A;
158
159 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
160 return false;
161 }
162
163 return (qk_ucis_state.codes[i] == KC_ENT ||
164 qk_ucis_state.codes[i] == KC_SPC);
165}
166
167__attribute__((weak))
168void qk_ucis_symbol_fallback (void) {
169 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
170 uint8_t code = qk_ucis_state.codes[i];
171 register_code(code);
172 unregister_code(code);
173 wait_ms(UNICODE_TYPE_DELAY);
174 }
175}
176
177void register_ucis(const char *hex) {
178 for(int i = 0; hex[i]; i++) {
179 uint8_t kc = 0;
180 char c = hex[i];
181
182 switch (c) {
183 case '0':
184 kc = KC_0;
185 break;
186 case '1' ... '9':
187 kc = c - '1' + KC_1;
188 break;
189 case 'a' ... 'f':
190 kc = c - 'a' + KC_A;
191 break;
192 case 'A' ... 'F':
193 kc = c - 'A' + KC_A;
194 break;
195 }
196
197 if (kc) {
198 register_code (kc);
199 unregister_code (kc);
200 wait_ms (UNICODE_TYPE_DELAY);
201 }
202 }
203}
204
205bool process_ucis (uint16_t keycode, keyrecord_t *record) {
206 uint8_t i;
207
208 if (!qk_ucis_state.in_progress)
209 return true;
210
211 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
212 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
213 return false;
214 }
215
216 if (!record->event.pressed)
217 return true;
218
219 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
220 qk_ucis_state.count++;
221
222 if (keycode == KC_BSPC) {
223 if (qk_ucis_state.count >= 2) {
224 qk_ucis_state.count -= 2;
225 return true;
226 } else {
227 qk_ucis_state.count--;
228 return false;
229 }
230 }
231
232 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
233 bool symbol_found = false;
234
235 for (i = qk_ucis_state.count; i > 0; i--) {
236 register_code (KC_BSPC);
237 unregister_code (KC_BSPC);
238 wait_ms(UNICODE_TYPE_DELAY);
239 }
240
241 if (keycode == KC_ESC) {
242 qk_ucis_state.in_progress = false;
243 return false;
244 }
245
246 unicode_input_start();
247 for (i = 0; ucis_symbol_table[i].symbol; i++) {
248 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
249 symbol_found = true;
250 register_ucis(ucis_symbol_table[i].code + 2);
251 break;
252 }
253 }
254 if (!symbol_found) {
255 qk_ucis_symbol_fallback();
256 }
257 unicode_input_finish();
258
259 qk_ucis_state.in_progress = false;
260 return false;
261 }
262 return true;
263}
264#endif