diff options
Diffstat (limited to 'users/replicaJunction/features/num_word.c')
-rw-r--r-- | users/replicaJunction/features/num_word.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/users/replicaJunction/features/num_word.c b/users/replicaJunction/features/num_word.c new file mode 100644 index 000000000..4cca5c19a --- /dev/null +++ b/users/replicaJunction/features/num_word.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* Copyright 2021 Joshua T. | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include "num_word.h" | ||
18 | |||
19 | static uint16_t num_word_timer = 0; | ||
20 | static bool is_num_word_on = false; | ||
21 | |||
22 | bool is_num_word_enabled(void) { | ||
23 | return is_num_word_on; | ||
24 | } | ||
25 | |||
26 | void enable_num_word(void) { | ||
27 | if (is_num_word_on) return; | ||
28 | is_num_word_on = true; | ||
29 | layer_on(L_NUMBERS); | ||
30 | } | ||
31 | |||
32 | void disable_num_word(void) { | ||
33 | if (!is_num_word_on) return; | ||
34 | is_num_word_on = false; | ||
35 | layer_off(L_NUMBERS); | ||
36 | } | ||
37 | |||
38 | void toggle_num_word(void) { | ||
39 | if (is_num_word_on) { | ||
40 | disable_num_word(); | ||
41 | } | ||
42 | else { | ||
43 | enable_num_word(); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | bool should_terminate_num_word(uint16_t keycode, const keyrecord_t *record) { | ||
48 | switch (keycode) { | ||
49 | // Keycodes which should not disable num word mode. | ||
50 | // We could probably be more brief with these definitions by using | ||
51 | // a couple more ranges, but I believe "explicit is better than | ||
52 | // implicit" | ||
53 | case KC_1 ... KC_0: | ||
54 | case KC_EQL: | ||
55 | case KC_SCLN: | ||
56 | case KC_MINS: | ||
57 | case KC_DOT: | ||
58 | |||
59 | // Numpad keycodes | ||
60 | case KC_P1 ... KC_P0: | ||
61 | case KC_PSLS ... KC_PPLS: | ||
62 | case KC_PDOT: | ||
63 | |||
64 | // Misc | ||
65 | case KC_UNDS: | ||
66 | case KC_BSPC: | ||
67 | return false; | ||
68 | |||
69 | default: | ||
70 | if (record->event.pressed) { | ||
71 | return true; | ||
72 | } | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | // Should be unreachable | ||
77 | return false; | ||
78 | } | ||
79 | |||
80 | |||
81 | bool process_record_num_word(uint16_t keycode, const keyrecord_t *record) { | ||
82 | // Handle the custom keycodes that go with this feature | ||
83 | if (keycode == NUMWORD) { | ||
84 | if (record->event.pressed) { | ||
85 | enable_num_word(); | ||
86 | num_word_timer = timer_read(); | ||
87 | return false; | ||
88 | } | ||
89 | else { | ||
90 | if (timer_elapsed(num_word_timer) > TAPPING_TERM) { | ||
91 | // If the user held the key longer than TAPPING_TERM, | ||
92 | // consider it a hold, and disable the behavior on | ||
93 | // key release. | ||
94 | disable_num_word(); | ||
95 | return false; | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | // Other than the custom keycodes, nothing else in this feature will | ||
101 | // activate if the behavior is not on, so allow QMK to handle the | ||
102 | // event as usual | ||
103 | if (!is_num_word_on) return true; | ||
104 | |||
105 | // Nothing else acts on key release, either | ||
106 | if (!record->event.pressed) { | ||
107 | return true; | ||
108 | } | ||
109 | |||
110 | // Get the base keycode of a mod or layer tap key | ||
111 | switch (keycode) { | ||
112 | case QK_MOD_TAP ... QK_MOD_TAP_MAX: | ||
113 | case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: | ||
114 | case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: | ||
115 | // Earlier return if this has not been considered tapped yet | ||
116 | if (record->tap.count == 0) | ||
117 | return true; | ||
118 | keycode = keycode & 0xFF; | ||
119 | break; | ||
120 | default: | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (should_terminate_num_word(keycode, record)) { | ||
125 | disable_num_word(); | ||
126 | } | ||
127 | |||
128 | return true; | ||
129 | } | ||