summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/dynamic_macro.h226
-rw-r--r--quantum/process_keycode/process_tap_dance.c130
-rw-r--r--quantum/process_keycode/process_tap_dance.h9
-rw-r--r--quantum/process_keycode/process_unicode.c205
-rw-r--r--quantum/process_keycode/process_unicode.h38
-rw-r--r--quantum/quantum.c62
-rw-r--r--quantum/quantum.h3
7 files changed, 565 insertions, 108 deletions
diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h
new file mode 100644
index 0000000000..a3ad61bc7e
--- /dev/null
+++ b/quantum/dynamic_macro.h
@@ -0,0 +1,226 @@
+/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */
+#ifndef DYNAMIC_MACROS_H
+#define DYNAMIC_MACROS_H
+
+#include "action_layer.h"
+
+#ifndef DYNAMIC_MACRO_SIZE
+/* May be overridden with a custom value. Be aware that the effective
+ * macro length is half of this value: each keypress is recorded twice
+ * because of the down-event and up-event. This is not a bug, it's the
+ * intended behavior. */
+#define DYNAMIC_MACRO_SIZE 256
+#endif
+
+/* DYNAMIC_MACRO_RANGE must be set as the last element of user's
+ * "planck_keycodes" enum prior to including this header. This allows
+ * us to 'extend' it.
+ */
+enum dynamic_macro_keycodes {
+ DYN_REC_START1 = DYNAMIC_MACRO_RANGE,
+ DYN_REC_START2,
+ DYN_MACRO_PLAY1,
+ DYN_MACRO_PLAY2,
+};
+
+/* Blink the LEDs to notify the user about some event. */
+void dynamic_macro_led_blink(void)
+{
+ backlight_toggle();
+ _delay_ms(100);
+ backlight_toggle();
+}
+
+/**
+ * Start recording of the dynamic macro.
+ *
+ * @param[out] macro_pointer The new macro buffer iterator.
+ * @param[in] macro_buffer The macro buffer used to initialize macro_pointer.
+ */
+void dynamic_macro_record_start(
+ keyrecord_t **macro_pointer, keyrecord_t *macro_buffer)
+{
+ dynamic_macro_led_blink();
+
+ clear_keyboard();
+ layer_clear();
+ *macro_pointer = macro_buffer;
+}
+
+/**
+ * Play the dynamic macro.
+ *
+ * @param macro_buffer[in] The beginning of the macro buffer being played.
+ * @param macro_end[in] The element after the last macro buffer element.
+ * @param direction[in] Either +1 or -1, which way to iterate the buffer.
+ */
+void dynamic_macro_play(
+ keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction)
+{
+ uint32_t saved_layer_state = layer_state;
+
+ clear_keyboard();
+ layer_clear();
+
+ while (macro_buffer != macro_end) {
+ process_record(macro_buffer);
+ macro_buffer += direction;
+ }
+
+ clear_keyboard();
+
+ layer_state = saved_layer_state;
+}
+
+/**
+ * Record a single key in a dynamic macro.
+ *
+ * @param macro_pointer[in,out] The current buffer position.
+ * @param macro_end2[in] The end of the other macro which shouldn't be overwritten.
+ * @param direction[in] Either +1 or -1, which way to iterate the buffer.
+ * @param record[in] The current keypress.
+ */
+void dynamic_macro_record_key(
+ keyrecord_t **macro_pointer,
+ keyrecord_t *macro_end2,
+ int8_t direction,
+ keyrecord_t *record)
+{
+ if (*macro_pointer + direction != macro_end2) {
+ **macro_pointer = *record;
+ *macro_pointer += direction;
+ } else {
+ /* Notify about the end of buffer. The blinks are paired
+ * because they should happen on both down and up events. */
+ backlight_toggle();
+ }
+}
+
+/**
+ * End recording of the dynamic macro. Essentially just update the
+ * pointer to the end of the macro.
+ */
+void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end)
+{
+ dynamic_macro_led_blink();
+
+ *macro_end = macro_pointer;
+}
+
+/* Handle the key events related to the dynamic macros. Should be
+ * called from process_record_user() like this:
+ *
+ * bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ * if (!process_record_dynamic_macro(keycode, record)) {
+ * return false;
+ * }
+ * <...THE REST OF THE FUNCTION...>
+ * }
+ */
+bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
+{
+ /* Both macros use the same buffer but read/write on different
+ * ends of it.
+ *
+ * Macro1 is written left-to-right starting from the beginning of
+ * the buffer.
+ *
+ * Macro2 is written right-to-left starting from the end of the
+ * buffer.
+ *
+ * &macro_buffer macro_end
+ * v v
+ * +------------------------------------------------------------+
+ * |>>>>>> MACRO1 >>>>>>| |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<|
+ * +------------------------------------------------------------+
+ * ^ ^
+ * r_macro_end r_macro_buffer
+ *
+ * During the recording when one macro encounters the end of the
+ * other macro, the recording is stopped. Apart from this, there
+ * are no arbitrary limits for the macros' length in relation to
+ * each other: for example one can either have two medium sized
+ * macros or one long macro and one short macro. Or even one empty
+ * and one using the whole buffer.
+ */
+ static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE];
+
+ /* Pointer to the first buffer element after the first macro.
+ * Initially points to the very beginning of the buffer since the
+ * macro is empty. */
+ static keyrecord_t *macro_end = macro_buffer;
+
+ /* The other end of the macro buffer. Serves as the beginning of
+ * the second macro. */
+ static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1;
+
+ /* Like macro_end but for the second macro. */
+ static keyrecord_t *r_macro_end = r_macro_buffer;
+
+ /* A persistent pointer to the current macro position (iterator)
+ * used during the recording. */
+ static keyrecord_t *macro_pointer = NULL;
+
+ /* 0 - no macro is being recorded right now
+ * 1,2 - either macro 1 or 2 is being recorded */
+ static uint8_t macro_id = 0;
+
+ if (macro_id == 0) {
+ /* No macro recording in progress. */
+ if (!record->event.pressed) {
+ switch (keycode) {
+ case DYN_REC_START1:
+ dynamic_macro_record_start(&macro_pointer, macro_buffer);
+ macro_id = 1;
+ return false;
+ case DYN_REC_START2:
+ dynamic_macro_record_start(&macro_pointer, r_macro_buffer);
+ macro_id = 2;
+ return false;
+ case DYN_MACRO_PLAY1:
+ dynamic_macro_play(macro_buffer, macro_end, +1);
+ return false;
+ case DYN_MACRO_PLAY2:
+ dynamic_macro_play(r_macro_buffer, r_macro_end, -1);
+ return false;
+ }
+ }
+ } else {
+ /* A macro is being recorded right now. */
+ switch (keycode) {
+ case MO(_DYN):
+ /* Use the layer key used to access the macro recording as
+ * a stop button. */
+ if (record->event.pressed) { /* Ignore the initial release
+ * just after the recoding
+ * starts. */
+ switch (macro_id) {
+ case 1:
+ dynamic_macro_record_end(macro_pointer, &macro_end);
+ break;
+ case 2:
+ dynamic_macro_record_end(macro_pointer, &r_macro_end);
+ break;
+ }
+ macro_id = 0;
+ }
+ return false;
+ default:
+ /* Store the key in the macro buffer and process it normally. */
+ switch (macro_id) {
+ case 1:
+ dynamic_macro_record_key(&macro_pointer, r_macro_end, +1, record);
+ break;
+ case 2:
+ dynamic_macro_record_key(&macro_pointer, macro_end, -1, record);
+ break;
+ }
+ return true;
+ break;
+ }
+ }
+
+ return true;
+}
+
+#endif
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 5429e34383..07de3ecb8f 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -1,26 +1,16 @@
#include "quantum.h"
+#include "action_tapping.h"
-static qk_tap_dance_state_t qk_tap_dance_state;
-bool td_debug_enable = false;
-
-#if CONSOLE_ENABLE
-#define td_debug(s) if (td_debug_enable) \
- { \
- xprintf ("D:tap_dance:%s:%s = { keycode = %d, count = %d, active = %d, pressed = %d }\n", __FUNCTION__, s, \
- qk_tap_dance_state.keycode, qk_tap_dance_state.count, \
- qk_tap_dance_state.active, qk_tap_dance_state.pressed); \
- }
-#else
-#define td_debug(s)
-#endif
+static uint16_t last_td;
+static int8_t highest_td = -1;
void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
if (state->count == 1) {
- register_code (pair->kc1);
+ register_code16 (pair->kc1);
} else if (state->count == 2) {
- register_code (pair->kc2);
+ register_code16 (pair->kc2);
}
}
@@ -28,105 +18,117 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
if (state->count == 1) {
- unregister_code (pair->kc1);
+ unregister_code16 (pair->kc1);
} else if (state->count == 2) {
- unregister_code (pair->kc2);
+ unregister_code16 (pair->kc2);
}
}
static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
- void *user_data,
- qk_tap_dance_user_fn_t fn)
+ void *user_data,
+ qk_tap_dance_user_fn_t fn)
{
if (fn) {
fn(state, user_data);
}
}
-static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action)
+static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
{
- td_debug("trigger");
- _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap);
+ _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
}
-static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action)
+static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
{
- td_debug("trigger");
- _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished);
+ if (action->state.finished)
+ return;
+ action->state.finished = true;
+ _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
}
-static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action)
+static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
{
- td_debug("trigger")
- _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset);
+ _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
}
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
- bool r = true;
uint16_t idx = keycode - QK_TAP_DANCE;
- qk_tap_dance_action_t action;
+ qk_tap_dance_action_t *action;
+
+ if (last_td && last_td != keycode) {
+ (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
+ }
switch(keycode) {
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
- action = tap_dance_actions[idx];
-
- process_tap_dance_action_on_each_tap (action);
- if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) {
- process_tap_dance_action_on_dance_finished (action);
- } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
- reset_tap_dance (&qk_tap_dance_state);
- } else {
- r = false;
- }
+ if ((int16_t)idx > highest_td)
+ highest_td = idx;
+ action = &tap_dance_actions[idx];
- qk_tap_dance_state.active = true;
- qk_tap_dance_state.pressed = record->event.pressed;
+ action->state.keycode = keycode;
+ action->state.pressed = record->event.pressed;
if (record->event.pressed) {
- qk_tap_dance_state.keycode = keycode;
- qk_tap_dance_state.timer = timer_read ();
- qk_tap_dance_state.count++;
+ action->state.count++;
+ action->state.timer = timer_read();
+
+ if (last_td && last_td != keycode) {
+ qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
+ paction->state.interrupted = true;
+ process_tap_dance_action_on_dance_finished (paction);
+ reset_tap_dance (&paction->state);
+ }
}
+ last_td = keycode;
+
break;
default:
- if (qk_tap_dance_state.keycode) {
- // if we are here, the tap dance was interrupted by a different key
- idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
- action = tap_dance_actions[idx];
+ if (!record->event.pressed)
+ return true;
+
+ if (highest_td == -1)
+ return true;
- process_tap_dance_action_on_each_tap (action);
+ for (int i = 0; i <= highest_td; i++) {
+ action = &tap_dance_actions[i];
+ if (action->state.count == 0)
+ continue;
+ action->state.interrupted = true;
process_tap_dance_action_on_dance_finished (action);
- reset_tap_dance (&qk_tap_dance_state);
- qk_tap_dance_state.active = false;
+ reset_tap_dance (&action->state);
}
break;
}
- return r;
+ return true;
}
void matrix_scan_tap_dance () {
- if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) {
- // if we are here, the tap dance was timed out
- uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
- qk_tap_dance_action_t action = tap_dance_actions[idx];
+ if (highest_td == -1)
+ return;
+
+ for (int i = 0; i <= highest_td; i++) {
+ qk_tap_dance_action_t *action = &tap_dance_actions[i];
- process_tap_dance_action_on_dance_finished (action);
- reset_tap_dance (&qk_tap_dance_state);
+ if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
+ process_tap_dance_action_on_dance_finished (action);
+ reset_tap_dance (&action->state);
+ }
}
}
void reset_tap_dance (qk_tap_dance_state_t *state) {
- uint16_t idx = state->keycode - QK_TAP_DANCE;
- qk_tap_dance_action_t action;
+ qk_tap_dance_action_t *action;
if (state->pressed)
return;
- action = tap_dance_actions[idx];
+ action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
+
process_tap_dance_action_on_reset (action);
- state->keycode = 0;
state->count = 0;
- state->active = false;
+ state->interrupted = false;
+ state->finished = false;
+ last_td = 0;
}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index 6a1258067e..d7b857bdc6 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -11,8 +11,9 @@ typedef struct
uint8_t count;
uint16_t keycode;
uint16_t timer;
- bool active:1;
- bool pressed:1;
+ bool interrupted;
+ bool pressed;
+ bool finished;
} qk_tap_dance_state_t;
#define TD(n) (QK_TAP_DANCE + n)
@@ -26,6 +27,7 @@ typedef struct
qk_tap_dance_user_fn_t on_dance_finished;
qk_tap_dance_user_fn_t on_reset;
} fn;
+ qk_tap_dance_state_t state;
void *user_data;
} qk_tap_dance_action_t;
@@ -48,8 +50,7 @@ typedef struct
.fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \
}
-extern const qk_tap_dance_action_t tap_dance_actions[];
-extern bool td_debug_enable;
+extern qk_tap_dance_action_t tap_dance_actions[];
/* To be used internally */
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index ad5d7f86b7..72c809c30e 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -13,45 +13,192 @@ uint16_t hex_to_keycode(uint8_t hex)
}
}
-void set_unicode_mode(uint8_t os_target)
+void set_unicode_input_mode(uint8_t os_target)
{
input_mode = os_target;
}
+void unicode_input_start (void) {
+ switch(input_mode) {
+ case UC_OSX:
+ register_code(KC_LALT);
+ break;
+ case UC_LNX:
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+ register_code(KC_U);
+ unregister_code(KC_U);
+ unregister_code(KC_LSFT);
+ unregister_code(KC_LCTL);
+ break;
+ case UC_WIN:
+ register_code(KC_LALT);
+ register_code(KC_PPLS);
+ unregister_code(KC_PPLS);
+ break;
+ }
+ wait_ms(UNICODE_TYPE_DELAY);
+}
+
+void unicode_input_finish (void) {
+ switch(input_mode) {
+ case UC_OSX:
+ case UC_WIN:
+ unregister_code(KC_LALT);
+ break;
+ case UC_LNX:
+ register_code(KC_SPC);
+ unregister_code(KC_SPC);
+ break;
+ }
+}
+
+void register_hex(uint16_t hex) {
+ for(int i = 3; i >= 0; i--) {
+ uint8_t digit = ((hex >> (i*4)) & 0xF);
+ register_code(hex_to_keycode(digit));
+ unregister_code(hex_to_keycode(digit));
+ }
+}
+
bool process_unicode(uint16_t keycode, keyrecord_t *record) {
if (keycode > QK_UNICODE && record->event.pressed) {
uint16_t unicode = keycode & 0x7FFF;
- switch(input_mode) {
- case UC_OSX:
- register_code(KC_LALT);
- break;
- case UC_LNX:
- register_code(KC_LCTL);
- register_code(KC_LSFT);
- register_code(KC_U);
- unregister_code(KC_U);
- break;
- case UC_WIN:
- register_code(KC_LALT);
- register_code(KC_PPLS);
- unregister_code(KC_PPLS);
- break;
+ unicode_input_start();
+ register_hex(unicode);
+ unicode_input_finish();
+ }
+ return true;
+}
+
+#ifdef UCIS_ENABLE
+void qk_ucis_start(void) {
+ qk_ucis_state.count = 0;
+ qk_ucis_state.in_progress = true;
+
+ qk_ucis_start_user();
+}
+
+__attribute__((weak))
+void qk_ucis_start_user(void) {
+ unicode_input_start();
+ register_hex(0x2328);
+ unicode_input_finish();
+}
+
+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;
+ }
+
+ 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);
+ wait_ms(UNICODE_TYPE_DELAY);
+ }
+}
+
+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;
}
- for(int i = 3; i >= 0; i--) {
- uint8_t digit = ((unicode >> (i*4)) & 0xF);
- register_code(hex_to_keycode(digit));
- unregister_code(hex_to_keycode(digit));
+
+ if (kc) {
+ register_code (kc);
+ unregister_code (kc);
+ wait_ms (UNICODE_TYPE_DELAY);
}
- switch(input_mode) {
- case UC_OSX:
- case UC_WIN:
- unregister_code(KC_LALT);
- break;
- case UC_LNX:
- unregister_code(KC_LCTL);
- unregister_code(KC_LSFT);
+ }
+}
+
+bool process_ucis (uint16_t keycode, keyrecord_t *record) {
+ uint8_t i;
+
+ if (!qk_ucis_state.in_progress)
+ return true;
+
+ if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
+ !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
+ 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) {
+ if (qk_ucis_state.count >= 2) {
+ qk_ucis_state.count -= 2;
+ return true;
+ } else {
+ 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--) {
+ register_code (KC_BSPC);
+ unregister_code (KC_BSPC);
+ wait_ms(UNICODE_TYPE_DELAY);
+ }
+
+ if (keycode == KC_ESC) {
+ qk_ucis_state.in_progress = false;
+ return false;
+ }
+
+ unicode_input_start();
+ 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);
break;
+ }
}
+ if (!symbol_found) {
+ qk_ucis_symbol_fallback();
+ }
+ unicode_input_finish();
+
+ qk_ucis_state.in_progress = false;
+ return false;
}
return true;
-} \ No newline at end of file
+}
+#endif
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index ca17f8f669..85364e8eb3 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -8,10 +8,46 @@
#define UC_WIN 2
#define UC_BSD 3
+#ifndef UNICODE_TYPE_DELAY
+#define UNICODE_TYPE_DELAY 10
+#endif
+
void set_unicode_input_mode(uint8_t os_target);
+void unicode_input_start(void);
+void unicode_input_finish(void);
+void register_hex(uint16_t hex);
bool process_unicode(uint16_t keycode, keyrecord_t *record);
+#ifdef UCIS_ENABLE
+#ifndef UCIS_MAX_SYMBOL_LENGTH
+#define UCIS_MAX_SYMBOL_LENGTH 32
+#endif
+
+typedef struct {
+ char *symbol;
+ char *code;
+} qk_ucis_symbol_t;
+
+struct {
+ uint8_t count;
+ uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
+ bool in_progress:1;
+} qk_ucis_state;
+
+#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
+#define UCIS_SYM(name, code) {name, #code}
+
+extern const qk_ucis_symbol_t ucis_symbol_table[];
+
+void qk_ucis_start(void);
+void qk_ucis_start_user(void);
+void qk_ucis_symbol_fallback (void);
+void register_ucis(const char *hex);
+bool process_ucis (uint16_t keycode, keyrecord_t *record);
+
+#endif
+
#define UC_BSPC UC(0x0008)
#define UC_SPC UC(0x0020)
@@ -119,4 +155,4 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record);
#define UC_TILD UC(0x007E)
#define UC_DEL UC(0x007F)
-#endif \ No newline at end of file
+#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index bc2da510f2..e3a20f43e0 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -1,5 +1,42 @@
#include "quantum.h"
+static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
+ switch (code) {
+ case QK_MODS ... QK_MODS_MAX:
+ break;
+ default:
+ return;
+ }
+
+ if (code & QK_LCTL)
+ f(KC_LCTL);
+ if (code & QK_LSFT)
+ f(KC_LSFT);
+ if (code & QK_LALT)
+ f(KC_LALT);
+ if (code & QK_LGUI)
+ f(KC_LGUI);
+
+ if (code & QK_RCTL)
+ f(KC_RCTL);
+ if (code & QK_RSFT)
+ f(KC_RSFT);
+ if (code & QK_RALT)
+ f(KC_RALT);
+ if (code & QK_RGUI)
+ f(KC_RGUI);
+}
+
+void register_code16 (uint16_t code) {
+ do_code16 (code, register_code);
+ register_code (code);
+}
+
+void unregister_code16 (uint16_t code) {
+ unregister_code (code);
+ do_code16 (code, unregister_code);
+}
+
__attribute__ ((weak))
bool process_action_kb(keyrecord_t *record) {
return true;
@@ -46,18 +83,20 @@ bool process_record_quantum(keyrecord_t *record) {
uint16_t keycode;
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
- uint8_t layer;
+ /* TODO: Use store_or_get_action() or a similar function. */
+ if (!disable_action_cache) {
+ uint8_t layer;
- if (record->event.pressed) {
- layer = layer_switch_get_layer(key);
- update_source_layers_cache(key, layer);
- } else {
- layer = read_source_layers_cache(key);
- }
- keycode = keymap_key_to_keycode(layer, key);
- #else
- keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
+ if (record->event.pressed) {
+ layer = layer_switch_get_layer(key);
+ update_source_layers_cache(key, layer);
+ } else {
+ layer = read_source_layers_cache(key);
+ }
+ keycode = keymap_key_to_keycode(layer, key);
+ } else
#endif
+ keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
// This is how you use actions here
// if (keycode == KC_LEAD) {
@@ -87,6 +126,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef UNICODE_ENABLE
process_unicode(keycode, record) &&
#endif
+ #ifdef UCIS_ENABLE
+ process_ucis(keycode, record) &&
+ #endif
true)) {
return false;
}
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 6e3fbcc792..0c60466495 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -83,6 +83,9 @@ void reset_keyboard(void);
void startup_user(void);
void shutdown_user(void);
+void register_code16 (uint16_t code);
+void unregister_code16 (uint16_t code);
+
#ifdef BACKLIGHT_ENABLE
void backlight_init_ports(void);