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