]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/process_keycode/process_unicode.c
6a30afe2933125f034f0eb3779a16ddf374f1704
[qmk_firmware.git] / quantum / process_keycode / process_unicode.c
1 #include "process_unicode.h"
2
3 static uint8_t input_mode;
4
5 __attribute__((weak))
6 uint16_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
17 void set_unicode_input_mode(uint8_t os_target)
18 {
19   input_mode = os_target;
20 }
21
22 uint8_t get_unicode_input_mode(void) {
23   return input_mode;
24 }
25
26 __attribute__((weak))
27 void 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   }
46   wait_ms(UNICODE_TYPE_DELAY);
47 }
48
49 __attribute__((weak))
50 void unicode_input_finish (void) {
51   switch(input_mode) {
52   case UC_OSX:
53   case UC_WIN:
54     unregister_code(KC_LALT);
55     break;
56   case UC_LNX:
57     register_code(KC_SPC);
58     unregister_code(KC_SPC);
59     break;
60   }
61 }
62
63 void register_hex(uint16_t hex) {
64   for(int i = 3; i >= 0; i--) {
65     uint8_t digit = ((hex >> (i*4)) & 0xF);
66     register_code(hex_to_keycode(digit));
67     unregister_code(hex_to_keycode(digit));
68   }
69 }
70
71 bool process_unicode(uint16_t keycode, keyrecord_t *record) {
72   if (keycode > QK_UNICODE && record->event.pressed) {
73     uint16_t unicode = keycode & 0x7FFF;
74     unicode_input_start();
75     register_hex(unicode);
76     unicode_input_finish();
77   }
78   return true;
79 }
80
81 #ifdef UCIS_ENABLE
82 qk_ucis_state_t qk_ucis_state;
83
84 void qk_ucis_start(void) {
85   qk_ucis_state.count = 0;
86   qk_ucis_state.in_progress = true;
87
88   qk_ucis_start_user();
89 }
90
91 __attribute__((weak))
92 void qk_ucis_start_user(void) {
93   unicode_input_start();
94   register_hex(0x2328);
95   unicode_input_finish();
96 }
97
98 static bool is_uni_seq(char *seq) {
99   uint8_t i;
100
101   for (i = 0; seq[i]; i++) {
102     uint16_t code;
103     if (('1' <= seq[i]) && (seq[i] <= '0'))
104       code = seq[i] - '1' + KC_1;
105     else
106       code = seq[i] - 'a' + KC_A;
107
108     if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
109       return false;
110   }
111
112   return (qk_ucis_state.codes[i] == KC_ENT ||
113           qk_ucis_state.codes[i] == KC_SPC);
114 }
115
116 __attribute__((weak))
117 void qk_ucis_symbol_fallback (void) {
118   for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
119     uint8_t code = qk_ucis_state.codes[i];
120     register_code(code);
121     unregister_code(code);
122     wait_ms(UNICODE_TYPE_DELAY);
123   }
124 }
125
126 void register_ucis(const char *hex) {
127   for(int i = 0; hex[i]; i++) {
128     uint8_t kc = 0;
129     char c = hex[i];
130
131     switch (c) {
132     case '0':
133       kc = KC_0;
134       break;
135     case '1' ... '9':
136       kc = c - '1' + KC_1;
137       break;
138     case 'a' ... 'f':
139       kc = c - 'a' + KC_A;
140       break;
141     case 'A' ... 'F':
142       kc = c - 'A' + KC_A;
143       break;
144     }
145
146     if (kc) {
147       register_code (kc);
148       unregister_code (kc);
149       wait_ms (UNICODE_TYPE_DELAY);
150     }
151   }
152 }
153
154 bool process_ucis (uint16_t keycode, keyrecord_t *record) {
155   uint8_t i;
156
157   if (!qk_ucis_state.in_progress)
158     return true;
159
160   if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
161       !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
162     return false;
163   }
164
165   if (!record->event.pressed)
166     return true;
167
168   qk_ucis_state.codes[qk_ucis_state.count] = keycode;
169   qk_ucis_state.count++;
170
171   if (keycode == KC_BSPC) {
172     if (qk_ucis_state.count >= 2) {
173       qk_ucis_state.count -= 2;
174       return true;
175     } else {
176       qk_ucis_state.count--;
177       return false;
178     }
179   }
180
181   if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
182     bool symbol_found = false;
183
184     for (i = qk_ucis_state.count; i > 0; i--) {
185       register_code (KC_BSPC);
186       unregister_code (KC_BSPC);
187       wait_ms(UNICODE_TYPE_DELAY);
188     }
189
190     if (keycode == KC_ESC) {
191       qk_ucis_state.in_progress = false;
192       return false;
193     }
194
195     unicode_input_start();
196     for (i = 0; ucis_symbol_table[i].symbol; i++) {
197       if (is_uni_seq (ucis_symbol_table[i].symbol)) {
198         symbol_found = true;
199         register_ucis(ucis_symbol_table[i].code + 2);
200         break;
201       }
202     }
203     if (!symbol_found) {
204       qk_ucis_symbol_fallback();
205     }
206     unicode_input_finish();
207
208     qk_ucis_state.in_progress = false;
209     return false;
210   }
211   return true;
212 }
213 #endif