summaryrefslogtreecommitdiffstats
path: root/keyboards/hhkb/keymaps/shela/action_pseudo_lut.c
blob: a15f5e5e0b307f1fd0c761cb53bf415396607fde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "quantum.h"
#include "command.h"
#include "action_pseudo_lut.h"

static uint8_t send_key_shift_bit[SHIFT_BIT_SIZE];

/*
 * Pseudo layout action.
 * This action converts a keycode in order to output the character according to the keymap you specified
 * still your keyboard layout recognized wrongly on your OS.
 * Memo: Using other layer keymap to get keycode
 */
void action_pseudo_lut(keyrecord_t *record, uint8_t base_keymap_id, const uint16_t (*keymap)[2]) {
    uint8_t prev_shift;
    uint16_t keycode;
    uint16_t pseudo_keycode;

    /* get keycode from keymap you specified */
    keycode = keymap_key_to_keycode(base_keymap_id, record->event.key);

    prev_shift = keyboard_report->mods & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT));

    if (record->event.pressed) {
        /* when magic commands entered, keycode does not converted */
        if (IS_COMMAND()) {
            if (prev_shift) {
                add_shift_bit(keycode);
            }
            register_code(keycode);
            return;
        }

        if (prev_shift) {
            pseudo_keycode = convert_keycode(keymap, keycode, true);
            dprintf("pressed: %02X, converted: %04X\n", keycode, pseudo_keycode);
            add_shift_bit(keycode);

            if (IS_LSFT(pseudo_keycode)) {
                register_code(QK_LSFT ^ pseudo_keycode);
            } else {
                /* delete shift mod temporarily */
                del_mods(prev_shift);
                send_keyboard_report();
                register_code(pseudo_keycode);
                add_mods(prev_shift);
                send_keyboard_report();
            }
        } else {
            pseudo_keycode = convert_keycode(keymap, keycode, false);
            dprintf("pressed: %02X, converted: %04X\n", keycode, pseudo_keycode);

            if (IS_LSFT(pseudo_keycode)) {
                add_weak_mods(MOD_BIT(KC_LSFT));
                send_keyboard_report();
                register_code(QK_LSFT ^ pseudo_keycode);
                /* on Windows, prevent key repeat to avoid unintended output */
                unregister_code(QK_LSFT ^ pseudo_keycode);
                del_weak_mods(MOD_BIT(KC_LSFT));
                send_keyboard_report();
            } else {
                register_code(pseudo_keycode);
            }
        }
    } else {
        if (get_shift_bit(keycode)) {
            del_shift_bit(keycode);
            pseudo_keycode = convert_keycode(keymap, keycode, true);
        } else {
            pseudo_keycode = convert_keycode(keymap, keycode, false);
        }
        dprintf("released: %02X, converted: %04X\n", keycode, pseudo_keycode);

        if (IS_LSFT(pseudo_keycode)) {
            unregister_code(QK_LSFT ^ pseudo_keycode);
        } else {
            unregister_code(pseudo_keycode);
        }
    }
}

uint16_t convert_keycode(const uint16_t (*keymap)[2], uint16_t keycode, bool shift_modded)
{
    uint16_t pseudo_keycode;

    switch (keycode) {
        case KC_A ... KC_CAPSLOCK:
#if defined(__AVR__)
            if (shift_modded) {
                pseudo_keycode = pgm_read_word(&keymap[keycode][1]);
            } else {
                pseudo_keycode = pgm_read_word(&keymap[keycode][0]);
            }
#else
            if (shift_modded) {
                pseudo_keycode = keymap[keycode][1];
            } else {
                pseudo_keycode = keymap[keycode][0];
            }
#endif
            /* if undefined, use got keycode as it is */
            if (pseudo_keycode == 0x00) {
                if (shift_modded) {
                    pseudo_keycode = S(keycode);
                } else {
                    pseudo_keycode = keycode;
                }
            }
            break;
        default:
            if (shift_modded) {
                pseudo_keycode = S(keycode);
            } else {
                pseudo_keycode = keycode;
            }
            break;
    }
    return pseudo_keycode;
}

uint8_t get_shift_bit(uint16_t keycode) {
    if ((keycode >> 3) < SHIFT_BIT_SIZE) {
        return send_key_shift_bit[keycode >> 3] & (1 << (keycode & 7));
    } else {
        dprintf("get_shift_bit: Can't get shift bit. keycode: %02X\n", keycode);
        return 0;
    }
}

void add_shift_bit(uint16_t keycode) {
    if ((keycode >> 3) < SHIFT_BIT_SIZE) {
        send_key_shift_bit[keycode >> 3] |= (1 << (keycode & 7));
    } else {
        dprintf("add_shift_bit: Can't add shift bit. keycode: %02X\n", keycode);
    }
}

void del_shift_bit(uint16_t keycode) {
    if ((keycode >> 3) < SHIFT_BIT_SIZE) {
        send_key_shift_bit[keycode >> 3] &= ~(1 << (keycode & 7));
    } else {
        dprintf("del_shift_bit: Can't delete shift bit. keycode: %02X\n", keycode);
    }
}