aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorJason Laqua <jlaqua118@gmail.com>2020-06-18 02:07:34 -0500
committerGitHub <noreply@github.com>2020-06-18 08:07:34 +0100
commitf7eb030e917a8fa360ad7cc7bb26d804cf4c5f6c (patch)
tree8415ddb70ed9fa1cfea2651a6ef950483648d851 /quantum
parentaae1814319c4992471d074ed18b8b7b4842b0a66 (diff)
downloadqmk_firmware-f7eb030e917a8fa360ad7cc7bb26d804cf4c5f6c.tar.gz
qmk_firmware-f7eb030e917a8fa360ad7cc7bb26d804cf4c5f6c.zip
Standardize how unicode is processed (fixes #8768) (#8770)
Co-authored-by: Konstantin Đorđević <vomindoraan@gmail.com>
Diffstat (limited to 'quantum')
-rw-r--r--quantum/process_keycode/process_ucis.c97
-rw-r--r--quantum/process_keycode/process_ucis.h26
-rw-r--r--quantum/process_keycode/process_unicode_common.c25
-rw-r--r--quantum/process_keycode/process_unicode_common.h2
-rw-r--r--quantum/process_keycode/process_unicodemap.c21
5 files changed, 81 insertions, 90 deletions
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index 024077317..2541d6eb2 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -27,7 +27,7 @@ void qk_ucis_start(void) {
27 27
28__attribute__((weak)) void qk_ucis_start_user(void) { 28__attribute__((weak)) void qk_ucis_start_user(void) {
29 unicode_input_start(); 29 unicode_input_start();
30 register_hex(0x2328); 30 register_hex(0x2328); // ⌨
31 unicode_input_finish(); 31 unicode_input_finish();
32} 32}
33 33
@@ -35,74 +35,54 @@ __attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}
35 35
36static bool is_uni_seq(char *seq) { 36static bool is_uni_seq(char *seq) {
37 uint8_t i; 37 uint8_t i;
38
39 for (i = 0; seq[i]; i++) { 38 for (i = 0; seq[i]; i++) {
40 uint16_t code; 39 uint16_t keycode;
41 if (('1' <= seq[i]) && (seq[i] <= '0')) 40 if ('1' <= seq[i] && seq[i] <= '0') {
42 code = seq[i] - '1' + KC_1; 41 keycode = seq[i] - '1' + KC_1;
43 else 42 } else {
44 code = seq[i] - 'a' + KC_A; 43 keycode = seq[i] - 'a' + KC_A;
45 44 }
46 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) return false; 45 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != keycode) {
46 return false;
47 }
47 } 48 }
48 49 return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;
49 return (qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC);
50} 50}
51 51
52__attribute__((weak)) void qk_ucis_symbol_fallback(void) { 52__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
53 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) { 53 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
54 uint8_t code = qk_ucis_state.codes[i]; 54 uint8_t keycode = qk_ucis_state.codes[i];
55 register_code(code); 55 register_code(keycode);
56 unregister_code(code); 56 unregister_code(keycode);
57 wait_ms(UNICODE_TYPE_DELAY); 57 wait_ms(UNICODE_TYPE_DELAY);
58 } 58 }
59} 59}
60 60
61__attribute__((weak)) void qk_ucis_cancel(void) {} 61__attribute__((weak)) void qk_ucis_cancel(void) {}
62 62
63void register_ucis(const char *hex) { 63void register_ucis(const uint32_t *code_points) {
64 for (int i = 0; hex[i]; i++) { 64 for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) {
65 uint8_t kc = 0; 65 register_unicode(code_points[i]);
66 char c = hex[i]; 66 wait_ms(UNICODE_TYPE_DELAY);
67
68 switch (c) {
69 case '0':
70 kc = KC_0;
71 break;
72 case '1' ... '9':
73 kc = c - '1' + KC_1;
74 break;
75 case 'a' ... 'f':
76 kc = c - 'a' + KC_A;
77 break;
78 case 'A' ... 'F':
79 kc = c - 'A' + KC_A;
80 break;
81 }
82
83 if (kc) {
84 register_code(kc);
85 unregister_code(kc);
86 wait_ms(UNICODE_TYPE_DELAY);
87 }
88 } 67 }
89} 68}
90 69
91bool process_ucis(uint16_t keycode, keyrecord_t *record) { 70bool process_ucis(uint16_t keycode, keyrecord_t *record) {
92 uint8_t i; 71 if (!qk_ucis_state.in_progress || !record->event.pressed) {
93 72 return true;
94 if (!qk_ucis_state.in_progress) return true; 73 }
95 74
96 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) { 75 bool special = keycode == KC_SPC || keycode == KC_ENT ||
76 keycode == KC_ESC || keycode == KC_BSPC;
77 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
97 return false; 78 return false;
98 } 79 }
99 80
100 if (!record->event.pressed) return true;
101
102 qk_ucis_state.codes[qk_ucis_state.count] = keycode; 81 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
103 qk_ucis_state.count++; 82 qk_ucis_state.count++;
104 83
105 if (keycode == KC_BSPC) { 84 switch (keycode) {
85 case KC_BSPC:
106 if (qk_ucis_state.count >= 2) { 86 if (qk_ucis_state.count >= 2) {
107 qk_ucis_state.count -= 2; 87 qk_ucis_state.count -= 2;
108 return true; 88 return true;
@@ -110,12 +90,11 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
110 qk_ucis_state.count--; 90 qk_ucis_state.count--;
111 return false; 91 return false;
112 } 92 }
113 }
114 93
115 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) { 94 case KC_SPC:
116 bool symbol_found = false; 95 case KC_ENT:
117 96 case KC_ESC:
118 for (i = qk_ucis_state.count; i > 0; i--) { 97 for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
119 register_code(KC_BSPC); 98 register_code(KC_BSPC);
120 unregister_code(KC_BSPC); 99 unregister_code(KC_BSPC);
121 wait_ms(UNICODE_TYPE_DELAY); 100 wait_ms(UNICODE_TYPE_DELAY);
@@ -127,25 +106,25 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
127 return false; 106 return false;
128 } 107 }
129 108
130 unicode_input_start(); 109 uint8_t i;
110 bool symbol_found = false;
131 for (i = 0; ucis_symbol_table[i].symbol; i++) { 111 for (i = 0; ucis_symbol_table[i].symbol; i++) {
132 if (is_uni_seq(ucis_symbol_table[i].symbol)) { 112 if (is_uni_seq(ucis_symbol_table[i].symbol)) {
133 symbol_found = true; 113 symbol_found = true;
134 register_ucis(ucis_symbol_table[i].code + 2); 114 register_ucis(ucis_symbol_table[i].code_points);
135 break; 115 break;
136 } 116 }
137 } 117 }
138 if (!symbol_found) {
139 qk_ucis_symbol_fallback();
140 }
141 unicode_input_finish();
142
143 if (symbol_found) { 118 if (symbol_found) {
144 qk_ucis_success(i); 119 qk_ucis_success(i);
120 } else {
121 qk_ucis_symbol_fallback();
145 } 122 }
146 123
147 qk_ucis_state.in_progress = false; 124 qk_ucis_state.in_progress = false;
148 return false; 125 return false;
126
127 default:
128 return true;
149 } 129 }
150 return true;
151} 130}
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
index 0f93a198b..a667430bd 100644
--- a/quantum/process_keycode/process_ucis.h
+++ b/quantum/process_keycode/process_ucis.h
@@ -22,10 +22,13 @@
22#ifndef UCIS_MAX_SYMBOL_LENGTH 22#ifndef UCIS_MAX_SYMBOL_LENGTH
23# define UCIS_MAX_SYMBOL_LENGTH 32 23# define UCIS_MAX_SYMBOL_LENGTH 32
24#endif 24#endif
25#ifndef UCIS_MAX_CODE_POINTS
26# define UCIS_MAX_CODE_POINTS 3
27#endif
25 28
26typedef struct { 29typedef struct {
27 char *symbol; 30 char * symbol;
28 char *code; 31 uint32_t code_points[UCIS_MAX_CODE_POINTS];
29} qk_ucis_symbol_t; 32} qk_ucis_symbol_t;
30 33
31typedef struct { 34typedef struct {
@@ -36,12 +39,17 @@ typedef struct {
36 39
37extern qk_ucis_state_t qk_ucis_state; 40extern qk_ucis_state_t qk_ucis_state;
38 41
39#define UCIS_TABLE(...) \ 42// clang-format off
40 { \ 43
41 __VA_ARGS__, { NULL, NULL } \ 44#define UCIS_TABLE(...) \
45 { \
46 __VA_ARGS__, \
47 { NULL, {} } \
42 } 48 }
43#define UCIS_SYM(name, code) \ 49#define UCIS_SYM(name, ...) \
44 { name, #code } 50 { name, {__VA_ARGS__} }
51
52// clang-format on
45 53
46extern const qk_ucis_symbol_t ucis_symbol_table[]; 54extern const qk_ucis_symbol_t ucis_symbol_table[];
47 55
@@ -49,5 +57,7 @@ void qk_ucis_start(void);
49void qk_ucis_start_user(void); 57void qk_ucis_start_user(void);
50void qk_ucis_symbol_fallback(void); 58void qk_ucis_symbol_fallback(void);
51void qk_ucis_success(uint8_t symbol_index); 59void qk_ucis_success(uint8_t symbol_index);
52void register_ucis(const char *hex); 60
61void register_ucis(const uint32_t *code_points);
62
53bool process_ucis(uint16_t keycode, keyrecord_t *record); 63bool process_ucis(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index fb5021501..bea34c31e 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -171,6 +171,25 @@ void register_hex32(uint32_t hex) {
171 } 171 }
172} 172}
173 173
174void register_unicode(uint32_t code_point) {
175 if (code_point > 0x10FFFF || (code_point > 0xFFFF && unicode_config.input_mode == UC_WIN)) {
176 // Code point out of range, do nothing
177 return;
178 }
179
180 unicode_input_start();
181 if (code_point > 0xFFFF && unicode_config.input_mode == UC_MAC) {
182 // Convert code point to UTF-16 surrogate pair on macOS
183 code_point -= 0x10000;
184 uint32_t lo = code_point & 0x3FF, hi = (code_point & 0xFFC00) >> 10;
185 register_hex32(hi + 0xD800);
186 register_hex32(lo + 0xDC00);
187 } else {
188 register_hex32(code_point);
189 }
190 unicode_input_finish();
191}
192
174// clang-format off 193// clang-format off
175 194
176void send_unicode_hex_string(const char *str) { 195void send_unicode_hex_string(const char *str) {
@@ -236,14 +255,12 @@ void send_unicode_string(const char *str) {
236 return; 255 return;
237 } 256 }
238 257
239 int32_t code_point = 0;
240 while (*str) { 258 while (*str) {
259 int32_t code_point = 0;
241 str = decode_utf8(str, &code_point); 260 str = decode_utf8(str, &code_point);
242 261
243 if (code_point >= 0) { 262 if (code_point >= 0) {
244 unicode_input_start(); 263 register_unicode(code_point);
245 register_hex32(code_point);
246 unicode_input_finish();
247 } 264 }
248 } 265 }
249} 266}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index 4579fde8d..3082fbb5f 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -89,6 +89,8 @@ void unicode_input_cancel(void);
89 89
90void register_hex(uint16_t hex); 90void register_hex(uint16_t hex);
91void register_hex32(uint32_t hex); 91void register_hex32(uint32_t hex);
92void register_unicode(uint32_t code_point);
93
92void send_unicode_hex_string(const char *str); 94void send_unicode_hex_string(const char *str);
93void send_unicode_string(const char *str); 95void send_unicode_string(const char *str);
94 96
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index 2f402a2fd..789a90445 100644
--- a/quantum/process_keycode/process_unicodemap.c
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -36,25 +36,8 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
36 36
37bool process_unicodemap(uint16_t keycode, keyrecord_t *record) { 37bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {
38 if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) { 38 if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) {
39 unicode_input_start(); 39 uint32_t code_point = pgm_read_dword(unicode_map + unicodemap_index(keycode));
40 40 register_unicode(code_point);
41 uint32_t code = pgm_read_dword(unicode_map + unicodemap_index(keycode));
42 uint8_t input_mode = get_unicode_input_mode();
43
44 if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) {
45 // Character is out of range supported by the platform
46 unicode_input_cancel();
47 } else if (code > 0xFFFF && input_mode == UC_MAC) {
48 // Convert to UTF-16 surrogate pair on Mac
49 code -= 0x10000;
50 uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10;
51 register_hex32(hi + 0xD800);
52 register_hex32(lo + 0xDC00);
53 unicode_input_finish();
54 } else {
55 register_hex32(code);
56 unicode_input_finish();
57 }
58 } 41 }
59 return true; 42 return true;
60} 43}