summaryrefslogtreecommitdiff
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
parentaae1814319c4992471d074ed18b8b7b4842b0a66 (diff)
Standardize how unicode is processed (fixes #8768) (#8770)
Co-authored-by: Konstantin Đorđević <vomindoraan@gmail.com>
-rw-r--r--docs/feature_unicode.md13
-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
6 files changed, 89 insertions, 95 deletions
diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md
index a6f2cb4d0d..aedffe4ea2 100644
--- a/docs/feature_unicode.md
+++ b/docs/feature_unicode.md
@@ -66,13 +66,16 @@ Then define a table like this in your keymap file:
```c
const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE(
- UCIS_SYM("poop", 0x1F4A9), // 💩
- UCIS_SYM("rofl", 0x1F923), // 🤣
- UCIS_SYM("kiss", 0x1F619) // 😙
+ UCIS_SYM("poop", 0x1F4A9), // 💩
+ UCIS_SYM("rofl", 0x1F923), // 🤣
+ UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺
+ UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0), // ಠ_ಠ
);
```
-To use it, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl"), and hit Space or Enter. QMK should erase the "rofl" text and insert the laughing emoji.
+By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file.
+
+To use UCIS input, call `qk_ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji.
### Customization
@@ -90,7 +93,7 @@ Unicode input in QMK works by inputting a sequence of characters to the OS, sort
The following input modes are available:
-* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0xFFFF` (`0x10FFFF` with Unicode Map).
+* **`UC_MAC`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points).
To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar.
By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with another keycode.
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index 024077317f..2541d6eb26 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -27,7 +27,7 @@ void qk_ucis_start(void) {
__attribute__((weak)) void qk_ucis_start_user(void) {
unicode_input_start();
- register_hex(0x2328);
+ register_hex(0x2328); // ⌨
unicode_input_finish();
}
@@ -35,74 +35,54 @@ __attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}
static bool is_uni_seq(char *seq) {
uint8_t i;
-
for (i = 0; seq[i]; i++) {
- uint16_t code;
- if (('1' <= seq[i]) && (seq[i] <= '0'))
- code = seq[i] - '1' + KC_1;
- else
- code = seq[i] - 'a' + KC_A;
-
- if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) return false;
+ uint16_t keycode;
+ if ('1' <= seq[i] && seq[i] <= '0') {
+ keycode = seq[i] - '1' + KC_1;
+ } else {
+ keycode = seq[i] - 'a' + KC_A;
+ }
+ if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != keycode) {
+ return false;
+ }
}
-
- return (qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC);
+ return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;
}
__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
- uint8_t code = qk_ucis_state.codes[i];
- register_code(code);
- unregister_code(code);
+ uint8_t keycode = qk_ucis_state.codes[i];
+ register_code(keycode);
+ unregister_code(keycode);
wait_ms(UNICODE_TYPE_DELAY);
}
}
__attribute__((weak)) void qk_ucis_cancel(void) {}
-void register_ucis(const char *hex) {
- for (int i = 0; hex[i]; i++) {
- uint8_t kc = 0;
- char c = hex[i];
-
- switch (c) {
- case '0':
- kc = KC_0;
- break;
- case '1' ... '9':
- kc = c - '1' + KC_1;
- break;
- case 'a' ... 'f':
- kc = c - 'a' + KC_A;
- break;
- case 'A' ... 'F':
- kc = c - 'A' + KC_A;
- break;
- }
-
- if (kc) {
- register_code(kc);
- unregister_code(kc);
- wait_ms(UNICODE_TYPE_DELAY);
- }
+void register_ucis(const uint32_t *code_points) {
+ for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) {
+ register_unicode(code_points[i]);
+ wait_ms(UNICODE_TYPE_DELAY);
}
}
bool process_ucis(uint16_t keycode, keyrecord_t *record) {
- uint8_t i;
-
- if (!qk_ucis_state.in_progress) return true;
+ if (!qk_ucis_state.in_progress || !record->event.pressed) {
+ return true;
+ }
- if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
+ bool special = keycode == KC_SPC || keycode == KC_ENT ||
+ keycode == KC_ESC || keycode == KC_BSPC;
+ if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
return false;
}
- if (!record->event.pressed) return true;
-
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
qk_ucis_state.count++;
- if (keycode == KC_BSPC) {
+ switch (keycode) {
+ case KC_BSPC:
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
@@ -110,12 +90,11 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
qk_ucis_state.count--;
return false;
}
- }
- if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
- bool symbol_found = false;
-
- for (i = qk_ucis_state.count; i > 0; i--) {
+ case KC_SPC:
+ case KC_ENT:
+ case KC_ESC:
+ for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
register_code(KC_BSPC);
unregister_code(KC_BSPC);
wait_ms(UNICODE_TYPE_DELAY);
@@ -127,25 +106,25 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
return false;
}
- unicode_input_start();
+ uint8_t i;
+ bool symbol_found = false;
for (i = 0; ucis_symbol_table[i].symbol; i++) {
if (is_uni_seq(ucis_symbol_table[i].symbol)) {
symbol_found = true;
- register_ucis(ucis_symbol_table[i].code + 2);
+ register_ucis(ucis_symbol_table[i].code_points);
break;
}
}
- if (!symbol_found) {
- qk_ucis_symbol_fallback();
- }
- unicode_input_finish();
-
if (symbol_found) {
qk_ucis_success(i);
+ } else {
+ qk_ucis_symbol_fallback();
}
qk_ucis_state.in_progress = false;
return false;
+
+ default:
+ return true;
}
- return true;
}
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
index 0f93a198bb..a667430bda 100644
--- a/quantum/process_keycode/process_ucis.h
+++ b/quantum/process_keycode/process_ucis.h
@@ -22,10 +22,13 @@
#ifndef UCIS_MAX_SYMBOL_LENGTH
# define UCIS_MAX_SYMBOL_LENGTH 32
#endif
+#ifndef UCIS_MAX_CODE_POINTS
+# define UCIS_MAX_CODE_POINTS 3
+#endif
typedef struct {
- char *symbol;
- char *code;
+ char * symbol;
+ uint32_t code_points[UCIS_MAX_CODE_POINTS];
} qk_ucis_symbol_t;
typedef struct {
@@ -36,12 +39,17 @@ typedef struct {
extern qk_ucis_state_t qk_ucis_state;
-#define UCIS_TABLE(...) \
- { \
- __VA_ARGS__, { NULL, NULL } \
+// clang-format off
+
+#define UCIS_TABLE(...) \
+ { \
+ __VA_ARGS__, \
+ { NULL, {} } \
}
-#define UCIS_SYM(name, code) \
- { name, #code }
+#define UCIS_SYM(name, ...) \
+ { name, {__VA_ARGS__} }
+
+// clang-format on
extern const qk_ucis_symbol_t ucis_symbol_table[];
@@ -49,5 +57,7 @@ void qk_ucis_start(void);
void qk_ucis_start_user(void);
void qk_ucis_symbol_fallback(void);
void qk_ucis_success(uint8_t symbol_index);
-void register_ucis(const char *hex);
+
+void register_ucis(const uint32_t *code_points);
+
bool 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 fb50215012..bea34c31ea 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) {
}
}
+void register_unicode(uint32_t code_point) {
+ if (code_point > 0x10FFFF || (code_point > 0xFFFF && unicode_config.input_mode == UC_WIN)) {
+ // Code point out of range, do nothing
+ return;
+ }
+
+ unicode_input_start();
+ if (code_point > 0xFFFF && unicode_config.input_mode == UC_MAC) {
+ // Convert code point to UTF-16 surrogate pair on macOS
+ code_point -= 0x10000;
+ uint32_t lo = code_point & 0x3FF, hi = (code_point & 0xFFC00) >> 10;
+ register_hex32(hi + 0xD800);
+ register_hex32(lo + 0xDC00);
+ } else {
+ register_hex32(code_point);
+ }
+ unicode_input_finish();
+}
+
// clang-format off
void send_unicode_hex_string(const char *str) {
@@ -236,14 +255,12 @@ void send_unicode_string(const char *str) {
return;
}
- int32_t code_point = 0;
while (*str) {
+ int32_t code_point = 0;
str = decode_utf8(str, &code_point);
if (code_point >= 0) {
- unicode_input_start();
- register_hex32(code_point);
- unicode_input_finish();
+ register_unicode(code_point);
}
}
}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index 4579fde8d5..3082fbb5f0 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);
void register_hex(uint16_t hex);
void register_hex32(uint32_t hex);
+void register_unicode(uint32_t code_point);
+
void send_unicode_hex_string(const char *str);
void send_unicode_string(const char *str);
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index 2f402a2fd2..789a90445b 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) {
bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {
if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) {
- unicode_input_start();
-
- uint32_t code = pgm_read_dword(unicode_map + unicodemap_index(keycode));
- uint8_t input_mode = get_unicode_input_mode();
-
- if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) {
- // Character is out of range supported by the platform
- unicode_input_cancel();
- } else if (code > 0xFFFF && input_mode == UC_MAC) {
- // Convert to UTF-16 surrogate pair on Mac
- code -= 0x10000;
- uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10;
- register_hex32(hi + 0xD800);
- register_hex32(lo + 0xDC00);
- unicode_input_finish();
- } else {
- register_hex32(code);
- unicode_input_finish();
- }
+ uint32_t code_point = pgm_read_dword(unicode_map + unicodemap_index(keycode));
+ register_unicode(code_point);
}
return true;
}