summaryrefslogtreecommitdiffstats
path: root/users/edvorakjp/edvorakjp.c
diff options
context:
space:
mode:
Diffstat (limited to 'users/edvorakjp/edvorakjp.c')
-rw-r--r--users/edvorakjp/edvorakjp.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/users/edvorakjp/edvorakjp.c b/users/edvorakjp/edvorakjp.c
new file mode 100644
index 0000000000..cff1a123e4
--- /dev/null
+++ b/users/edvorakjp/edvorakjp.c
@@ -0,0 +1,246 @@
+#include "eeprom.h"
+#include "edvorakjp.h"
+
+bool japanese_mode;
+uint16_t time_on_pressed;
+
+edvorakjp_config_t edvorakjp_config;
+
+uint8_t eeconfig_read_edvorakjp(void) {
+ return eeprom_read_byte(EECONFIG_EDVORAK);
+}
+
+void eeconfig_update_edvorakjp(uint8_t val) {
+ eeprom_update_byte(EECONFIG_EDVORAK, val);
+}
+
+void dvorakj_layer_off(void) {
+ layer_off(_EDVORAKJ1);
+ layer_off(_EDVORAKJ2);
+}
+
+void update_japanese_mode(bool new_state) {
+ japanese_mode = new_state;
+ if (japanese_mode) {
+ if (edvorakjp_config.enable_kc_lang) {
+ SEND_STRING(SS_TAP(X_LANG1));
+ } else {
+ SEND_STRING(SS_LALT("`"));
+ }
+ } else {
+ dvorakj_layer_off();
+ if (edvorakjp_config.enable_kc_lang) {
+ SEND_STRING(SS_TAP(X_LANG2));
+ } else {
+ SEND_STRING(SS_LALT("`"));
+ }
+ }
+}
+
+void matrix_init_user(void) {
+ japanese_mode = false;
+ time_on_pressed = 0;
+ edvorakjp_config.raw = eeconfig_read_edvorakjp();
+
+ matrix_init_keymap();
+}
+
+__attribute__ ((weak))
+void matrix_init_keymap() {}
+
+uint32_t layer_state_set_user(uint32_t state) {
+ state = update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
+ return layer_state_set_keymap(state);
+}
+
+__attribute__ ((weak))
+uint32_t layer_state_set_keymap(uint32_t state) {
+ return state;
+}
+
+/*
+ * Each process_record_* methods defined here are
+ * return false if handle edvorak_keycodes, or return true others.
+ */
+__attribute__ ((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+bool process_record_edvorakjp_ext(uint16_t keycode, keyrecord_t *record) {
+ if (!(edvorakjp_config.enable_jp_extra_layer &&\
+ (default_layer_state == 1UL<<_EDVORAK) &&\
+ japanese_mode &&\
+ record->event.pressed)) {
+ return true;
+ }
+
+ // consonant keys
+ // layer_on(J1) or layer_on(J2) are defined based on key positions.
+ switch (keycode) {
+ // right hand's left side w/o N
+ case KC_F:
+ case KC_G:
+ case KC_R:
+ case KC_D:
+ case KC_T:
+ case KC_B:
+ case KC_H:
+ case KC_J:
+ layer_on(_EDVORAKJ1);
+ register_code(keycode);
+ unregister_code(keycode);
+ return false;
+
+ // N: toggle layer
+ case KC_N:
+ biton32(layer_state) == _EDVORAK ? layer_on(_EDVORAKJ1) : dvorakj_layer_off();
+ register_code(keycode);
+ unregister_code(keycode);
+ return false;
+
+ // left hand and right hand's right side
+ case KC_X:
+ case KC_C:
+ case KC_V:
+ case KC_Z:
+ case KC_P:
+ case KC_Y:
+ case KC_W:
+ case KC_Q:
+ case KC_S:
+ case KC_M:
+ case KC_K:
+ case KC_L:
+ layer_on(_EDVORAKJ2);
+ register_code(keycode);
+ unregister_code(keycode);
+ return false;
+ }
+
+ // vowel keys, symbol keys and modifier keys
+ dvorakj_layer_off();
+ switch (keycode) {
+ // combination vowel keys
+ case KC_AI:
+ SEND_STRING("ai");
+ return false;
+ case KC_OU:
+ SEND_STRING("ou");
+ return false;
+ case KC_EI:
+ SEND_STRING("ei");
+ return false;
+ case KC_ANN:
+ SEND_STRING("ann");
+ return false;
+ case KC_ONN:
+ SEND_STRING("onn");
+ return false;
+ case KC_ENN:
+ SEND_STRING("enn");
+ return false;
+ case KC_INN:
+ SEND_STRING("inn");
+ return false;
+ case KC_UNN:
+ SEND_STRING("unn");
+ return false;
+
+ // AOEIU and other (symbol, modifier) keys
+ default:
+ return true;
+ }
+}
+
+bool process_record_edvorakjp_config(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case KC_MAC:
+ edvorakjp_config.enable_kc_lang = true;
+ eeconfig_update_edvorakjp(edvorakjp_config.raw);
+ return false;
+ case KC_WIN:
+ edvorakjp_config.enable_kc_lang = false;
+ eeconfig_update_edvorakjp(edvorakjp_config.raw);
+ return false;
+ case KC_EXTON:
+ edvorakjp_config.enable_jp_extra_layer = true;
+ eeconfig_update_edvorakjp(edvorakjp_config.raw);
+ return false;
+ case KC_EXTOFF:
+ edvorakjp_config.enable_jp_extra_layer = false;
+ eeconfig_update_edvorakjp(edvorakjp_config.raw);
+ return false;
+ }
+ return true;
+}
+
+bool process_record_layer(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case EDVORAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_EDVORAK);
+ }
+ return false;
+ case QWERTY:
+ if (record->event.pressed) {
+ dvorakj_layer_off();
+ set_single_persistent_default_layer(_QWERTY);
+ }
+ return false;
+ case LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ time_on_pressed = record->event.time;
+ } else {
+ layer_off(_LOWER);
+
+ if (TIMER_DIFF_16(record->event.time, time_on_pressed) < TAPPING_TERM) {
+ update_japanese_mode(false);
+ }
+ time_on_pressed = 0;
+ }
+ return false;
+ case RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ time_on_pressed = record->event.time;
+ } else {
+ layer_off(_RAISE);
+
+ if (TIMER_DIFF_16(record->event.time, time_on_pressed) < TAPPING_TERM) {
+ update_japanese_mode(true);
+ }
+ time_on_pressed = 0;
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool process_record_ime(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case KC_JPN:
+ if (record->event.pressed) {
+ update_japanese_mode(true);
+ }
+ return false;
+ case KC_ENG:
+ if (record->event.pressed) {
+ update_japanese_mode(false);
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+
+ return process_record_keymap(keycode, record) &&\
+ process_record_edvorakjp_ext(keycode, record) &&\
+ process_record_edvorakjp_config(keycode, record) &&\
+ process_record_layer(keycode, record) &&\
+ process_record_ime(keycode, record);
+}