]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/action.c
Merge branch 'master' into sculpt2
[qmk_firmware.git] / tmk_core / common / action.c
1 /*
2 Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "host.h"
18 #include "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "led.h"
23 #include "backlight.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_macro.h"
27 #include "action_util.h"
28 #include "action.h"
29
30 #ifdef DEBUG_ACTION
31 #include "debug.h"
32 #else
33 #include "nodebug.h"
34 #endif
35
36
37 void action_exec(keyevent_t event)
38 {
39     if (!IS_NOEVENT(event)) {
40         dprint("\n---- action_exec: start -----\n");
41         dprint("EVENT: "); debug_event(event); dprintln();
42     }
43
44 #ifdef ONEHAND_ENABLE
45     if (!IS_NOEVENT(event)) {
46         process_hand_swap(&event);
47     }
48 #endif
49
50     keyrecord_t record = { .event = event };
51
52 #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
53     if (has_oneshot_layer_timed_out()) {
54         dprintf("Oneshot layer: timeout\n");
55         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
56     }
57 #endif
58
59 #ifndef NO_ACTION_TAPPING
60     action_tapping_process(record);
61 #else
62     process_record(&record);
63     if (!IS_NOEVENT(record.event)) {
64         dprint("processed: "); debug_record(record); dprintln();
65     }
66 #endif
67 }
68
69 #ifdef ONEHAND_ENABLE
70 bool swap_hands = false;
71
72 void process_hand_swap(keyevent_t *event) {
73     static swap_state_row_t swap_state[MATRIX_ROWS];
74
75     keypos_t pos = event->key;
76     swap_state_row_t col_bit = (swap_state_row_t)1<<pos.col;
77     bool do_swap = event->pressed ? swap_hands :
78                                     swap_state[pos.row] & (col_bit);
79
80     if (do_swap) {
81         event->key = hand_swap_config[pos.row][pos.col];
82         swap_state[pos.row] |= col_bit;
83     } else {
84         swap_state[pos.row] &= ~(col_bit);
85     }
86 }
87 #endif
88
89 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
90 bool disable_action_cache = false;
91
92 void process_record_nocache(keyrecord_t *record)
93 {
94     disable_action_cache = true;
95     process_record(record);
96     disable_action_cache = false;
97 }
98 #else
99 void process_record_nocache(keyrecord_t *record)
100 {
101     process_record(record);
102 }
103 #endif
104
105 __attribute__ ((weak))
106 bool process_record_quantum(keyrecord_t *record) {
107     return true;
108 }
109
110 void process_record(keyrecord_t *record)
111 {
112     if (IS_NOEVENT(record->event)) { return; }
113
114     if(!process_record_quantum(record))
115         return;
116
117     action_t action = store_or_get_action(record->event.pressed, record->event.key);
118     dprint("ACTION: "); debug_action(action);
119 #ifndef NO_ACTION_LAYER
120     dprint(" layer_state: "); layer_debug();
121     dprint(" default_layer_state: "); default_layer_debug();
122 #endif
123     dprintln();
124
125     process_action(record, action);
126 }
127
128 void process_action(keyrecord_t *record, action_t action)
129 {
130     bool do_release_oneshot = false;
131     keyevent_t event = record->event;
132 #ifndef NO_ACTION_TAPPING
133     uint8_t tap_count = record->tap.count;
134 #endif
135
136     if (event.pressed) {
137         // clear the potential weak mods left by previously pressed keys
138         clear_weak_mods();
139     }
140
141 #ifndef NO_ACTION_ONESHOT
142     // notice we only clear the one shot layer if the pressed key is not a modifier.
143     if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
144         clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
145         do_release_oneshot = !is_oneshot_layer_active();
146     }
147 #endif
148
149     switch (action.kind.id) {
150         /* Key and Mods */
151         case ACT_LMODS:
152         case ACT_RMODS:
153             {
154                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
155                                                                 action.key.mods<<4;
156                 if (event.pressed) {
157                     if (mods) {
158                         if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
159                             // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
160                             // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
161                             // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
162                             add_mods(mods);
163                         } else {
164                             add_weak_mods(mods);
165                         }
166                         send_keyboard_report();
167                     }
168                     register_code(action.key.code);
169                 } else {
170                     unregister_code(action.key.code);
171                     if (mods) {
172                         if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
173                             del_mods(mods);
174                         } else {
175                             del_weak_mods(mods);
176                         }
177                         send_keyboard_report();
178                     }
179                 }
180             }
181             break;
182 #ifndef NO_ACTION_TAPPING
183         case ACT_LMODS_TAP:
184         case ACT_RMODS_TAP:
185             {
186                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
187                                                                     action.key.mods<<4;
188                 switch (action.layer_tap.code) {
189     #ifndef NO_ACTION_ONESHOT
190                     case MODS_ONESHOT:
191                         // Oneshot modifier
192                         if (event.pressed) {
193                             if (tap_count == 0) {
194                                 dprint("MODS_TAP: Oneshot: 0\n");
195                                 register_mods(mods);
196                             } else if (tap_count == 1) {
197                                 dprint("MODS_TAP: Oneshot: start\n");
198                                 set_oneshot_mods(mods);
199                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
200                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
201                                 dprint("MODS_TAP: Toggling oneshot");
202                                 clear_oneshot_mods();
203                                 set_oneshot_locked_mods(mods);
204                                 register_mods(mods);
205                     #endif
206                             } else {
207                                 register_mods(mods);
208                             }
209                         } else {
210                             if (tap_count == 0) {
211                                 clear_oneshot_mods();
212                                 unregister_mods(mods);
213                             } else if (tap_count == 1) {
214                                 // Retain Oneshot mods
215                     #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
216                                 if (mods & get_mods()) {
217                                     clear_oneshot_locked_mods();
218                                     clear_oneshot_mods();
219                                     unregister_mods(mods);
220                                 }
221                             } else if (tap_count == ONESHOT_TAP_TOGGLE) {
222                                 // Toggle Oneshot Layer
223                     #endif
224                             } else {
225                                 clear_oneshot_mods();
226                                 unregister_mods(mods);
227                             }
228                         }
229                         break;
230     #endif
231                     case MODS_TAP_TOGGLE:
232                         if (event.pressed) {
233                             if (tap_count <= TAPPING_TOGGLE) {
234                                 register_mods(mods);
235                             }
236                         } else {
237                             if (tap_count < TAPPING_TOGGLE) {
238                                 unregister_mods(mods);
239                             }
240                         }
241                         break;
242                     default:
243                         if (event.pressed) {
244                             if (tap_count > 0) {
245 #ifndef IGNORE_MOD_TAP_INTERRUPT
246                                 if (record->tap.interrupted) {
247                                     dprint("mods_tap: tap: cancel: add_mods\n");
248                                     // ad hoc: set 0 to cancel tap
249                                     record->tap.count = 0;
250                                     register_mods(mods);
251                                 } else
252 #endif
253                                 {
254                                     dprint("MODS_TAP: Tap: register_code\n");
255                                     register_code(action.key.code);
256                                 }
257                             } else {
258                                 dprint("MODS_TAP: No tap: add_mods\n");
259                                 register_mods(mods);
260                             }
261                         } else {
262                             if (tap_count > 0) {
263                                 dprint("MODS_TAP: Tap: unregister_code\n");
264                                 unregister_code(action.key.code);
265                             } else {
266                                 dprint("MODS_TAP: No tap: add_mods\n");
267                                 unregister_mods(mods);
268                             }
269                         }
270                         break;
271                 }
272             }
273             break;
274 #endif
275 #ifdef EXTRAKEY_ENABLE
276         /* other HID usage */
277         case ACT_USAGE:
278             switch (action.usage.page) {
279                 case PAGE_SYSTEM:
280                     if (event.pressed) {
281                         host_system_send(action.usage.code);
282                     } else {
283                         host_system_send(0);
284                     }
285                     break;
286                 case PAGE_CONSUMER:
287                     if (event.pressed) {
288                         host_consumer_send(action.usage.code);
289                     } else {
290                         host_consumer_send(0);
291                     }
292                     break;
293             }
294             break;
295 #endif
296 #ifdef MOUSEKEY_ENABLE
297         /* Mouse key */
298         case ACT_MOUSEKEY:
299             if (event.pressed) {
300                 mousekey_on(action.key.code);
301                 mousekey_send();
302             } else {
303                 mousekey_off(action.key.code);
304                 mousekey_send();
305             }
306             break;
307 #endif
308 #ifndef NO_ACTION_LAYER
309         case ACT_LAYER:
310             if (action.layer_bitop.on == 0) {
311                 /* Default Layer Bitwise Operation */
312                 if (!event.pressed) {
313                     uint8_t shift = action.layer_bitop.part*4;
314                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
315                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
316                     switch (action.layer_bitop.op) {
317                         case OP_BIT_AND: default_layer_and(bits | mask); break;
318                         case OP_BIT_OR:  default_layer_or(bits | mask);  break;
319                         case OP_BIT_XOR: default_layer_xor(bits | mask); break;
320                         case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
321                     }
322                 }
323             } else {
324                 /* Layer Bitwise Operation */
325                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
326                                     (action.layer_bitop.on & ON_RELEASE)) {
327                     uint8_t shift = action.layer_bitop.part*4;
328                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
329                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
330                     switch (action.layer_bitop.op) {
331                         case OP_BIT_AND: layer_and(bits | mask); break;
332                         case OP_BIT_OR:  layer_or(bits | mask);  break;
333                         case OP_BIT_XOR: layer_xor(bits | mask); break;
334                         case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
335                     }
336                 }
337             }
338             break;
339     #ifndef NO_ACTION_TAPPING
340         case ACT_LAYER_TAP:
341         case ACT_LAYER_TAP_EXT:
342             switch (action.layer_tap.code) {
343                 case 0xe0 ... 0xef:
344                     /* layer On/Off with modifiers(left only) */
345                     if (event.pressed) {
346                         layer_on(action.layer_tap.val);
347                         register_mods(action.layer_tap.code & 0x0f);
348                     } else {
349                         layer_off(action.layer_tap.val);
350                         unregister_mods(action.layer_tap.code & 0x0f);
351                     }
352                     break;
353                 case OP_TAP_TOGGLE:
354                     /* tap toggle */
355                     if (event.pressed) {
356                         if (tap_count < TAPPING_TOGGLE) {
357                             layer_invert(action.layer_tap.val);
358                         }
359                     } else {
360                         if (tap_count <= TAPPING_TOGGLE) {
361                             layer_invert(action.layer_tap.val);
362                         }
363                     }
364                     break;
365                 case OP_ON_OFF:
366                     event.pressed ? layer_on(action.layer_tap.val) :
367                                     layer_off(action.layer_tap.val);
368                     break;
369                 case OP_OFF_ON:
370                     event.pressed ? layer_off(action.layer_tap.val) :
371                                     layer_on(action.layer_tap.val);
372                     break;
373                 case OP_SET_CLEAR:
374                     event.pressed ? layer_move(action.layer_tap.val) :
375                                     layer_clear();
376                     break;
377             #ifndef NO_ACTION_ONESHOT
378                 case OP_ONESHOT:
379                     // Oneshot modifier
380                 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
381                     do_release_oneshot = false;
382                     if (event.pressed) {
383                         del_mods(get_oneshot_locked_mods());
384                         if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
385                             reset_oneshot_layer();
386                             layer_off(action.layer_tap.val);
387                             break;
388                         } else if (tap_count < ONESHOT_TAP_TOGGLE) {
389                             layer_on(action.layer_tap.val);
390                             set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
391                         }
392                     } else {
393                         add_mods(get_oneshot_locked_mods());
394                         if (tap_count >= ONESHOT_TAP_TOGGLE) {
395                             reset_oneshot_layer();
396                             clear_oneshot_locked_mods();
397                             set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
398                         } else {
399                             clear_oneshot_layer_state(ONESHOT_PRESSED);
400                         }
401                     }
402                 #else
403                     if (event.pressed) {
404                         layer_on(action.layer_tap.val);
405                         set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
406                     } else {
407                         clear_oneshot_layer_state(ONESHOT_PRESSED);
408                         if (tap_count > 1) {
409                             clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
410                         }
411                     }
412                 #endif
413                     break;
414             #endif
415                 default:
416                     /* tap key */
417                     if (event.pressed) {
418                         if (tap_count > 0) {
419                             dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
420                             register_code(action.layer_tap.code);
421                         } else {
422                             dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
423                             layer_on(action.layer_tap.val);
424                         }
425                     } else {
426                         if (tap_count > 0) {
427                             dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
428                             unregister_code(action.layer_tap.code);
429                         } else {
430                             dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
431                             layer_off(action.layer_tap.val);
432                         }
433                     }
434                     break;
435             }
436             break;
437     #endif
438 #endif
439         /* Extentions */
440 #ifndef NO_ACTION_MACRO
441         case ACT_MACRO:
442             action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
443             break;
444 #endif
445 #ifdef BACKLIGHT_ENABLE
446         case ACT_BACKLIGHT:
447             if (!event.pressed) {
448                 switch (action.backlight.opt) {
449                     case BACKLIGHT_INCREASE:
450                         backlight_increase();
451                         break;
452                     case BACKLIGHT_DECREASE:
453                         backlight_decrease();
454                         break;
455                     case BACKLIGHT_TOGGLE:
456                         backlight_toggle();
457                         break;
458                     case BACKLIGHT_STEP:
459                         backlight_step();
460                         break;
461                     case BACKLIGHT_LEVEL:
462                         backlight_level(action.backlight.level);
463                         break;
464                 }
465             }
466             break;
467 #endif
468         case ACT_COMMAND:
469             break;
470 #ifdef ONEHAND_ENABLE
471         case ACT_SWAP_HANDS:
472             switch (action.swap.code) {
473                 case OP_SH_TOGGLE:
474                     if (event.pressed) {
475                         swap_hands = !swap_hands;
476                     }
477                     break;
478                 case OP_SH_ON_OFF:
479                     swap_hands = event.pressed;
480                     break;
481                 case OP_SH_OFF_ON:
482                     swap_hands = !event.pressed;
483                     break;
484                 case OP_SH_ON:
485                     if (!event.pressed) {
486                         swap_hands = true;
487                     }
488                     break;
489                 case OP_SH_OFF:
490                     if (!event.pressed) {
491                         swap_hands = false;
492                     }
493                     break;
494     #ifndef NO_ACTION_TAPPING
495                 case OP_SH_TAP_TOGGLE:
496                     /* tap toggle */
497                     if (tap_count > 0) {
498                         if (!event.pressed) {
499                             swap_hands = !swap_hands;
500                         }
501                     } else {
502                         swap_hands = event.pressed;
503                     }
504                     break;
505                 default:
506                     if (tap_count > 0) {
507                         if (event.pressed) {
508                             register_code(action.swap.code);
509                         } else {
510                             unregister_code(action.swap.code);
511                         }
512                     } else {
513                         swap_hands = event.pressed;
514                     }
515     #endif
516             }
517 #endif
518 #ifndef NO_ACTION_FUNCTION
519         case ACT_FUNCTION:
520             action_function(record, action.func.id, action.func.opt);
521             break;
522 #endif
523         default:
524             break;
525     }
526
527 #ifndef NO_ACTION_ONESHOT
528     /* Because we switch layers after a oneshot event, we need to release the
529      * key before we leave the layer or no key up event will be generated.
530      */
531     if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED )   ) {
532         record->event.pressed = false;
533         layer_on(get_oneshot_layer());
534         process_record(record);
535         layer_off(get_oneshot_layer());
536     }
537 #endif
538 }
539
540
541
542
543 /*
544  * Utilities for actions.
545  */
546 void register_code(uint8_t code)
547 {
548     if (code == KC_NO) {
549         return;
550     }
551
552 #ifdef LOCKING_SUPPORT_ENABLE
553     else if (KC_LOCKING_CAPS == code) {
554 #ifdef LOCKING_RESYNC_ENABLE
555         // Resync: ignore if caps lock already is on
556         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
557 #endif
558         add_key(KC_CAPSLOCK);
559         send_keyboard_report();
560         del_key(KC_CAPSLOCK);
561         send_keyboard_report();
562     }
563
564     else if (KC_LOCKING_NUM == code) {
565 #ifdef LOCKING_RESYNC_ENABLE
566         if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
567 #endif
568         add_key(KC_NUMLOCK);
569         send_keyboard_report();
570         del_key(KC_NUMLOCK);
571         send_keyboard_report();
572     }
573
574     else if (KC_LOCKING_SCROLL == code) {
575 #ifdef LOCKING_RESYNC_ENABLE
576         if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
577 #endif
578         add_key(KC_SCROLLLOCK);
579         send_keyboard_report();
580         del_key(KC_SCROLLLOCK);
581         send_keyboard_report();
582     }
583 #endif
584
585     else if IS_KEY(code) {
586         // TODO: should push command_proc out of this block?
587         if (command_proc(code)) return;
588
589 #ifndef NO_ACTION_ONESHOT
590 /* TODO: remove
591         if (oneshot_state.mods && !oneshot_state.disabled) {
592             uint8_t tmp_mods = get_mods();
593             add_mods(oneshot_state.mods);
594
595             add_key(code);
596             send_keyboard_report();
597
598             set_mods(tmp_mods);
599             send_keyboard_report();
600             oneshot_cancel();
601         } else
602 */
603 #endif
604         {
605             add_key(code);
606             send_keyboard_report();
607         }
608     }
609     else if IS_MOD(code) {
610         add_mods(MOD_BIT(code));
611         send_keyboard_report();
612     }
613     else if IS_SYSTEM(code) {
614         host_system_send(KEYCODE2SYSTEM(code));
615     }
616     else if IS_CONSUMER(code) {
617         host_consumer_send(KEYCODE2CONSUMER(code));
618     }
619 }
620
621 void unregister_code(uint8_t code)
622 {
623     if (code == KC_NO) {
624         return;
625     }
626
627 #ifdef LOCKING_SUPPORT_ENABLE
628     else if (KC_LOCKING_CAPS == code) {
629 #ifdef LOCKING_RESYNC_ENABLE
630         // Resync: ignore if caps lock already is off
631         if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
632 #endif
633         add_key(KC_CAPSLOCK);
634         send_keyboard_report();
635         del_key(KC_CAPSLOCK);
636         send_keyboard_report();
637     }
638
639     else if (KC_LOCKING_NUM == code) {
640 #ifdef LOCKING_RESYNC_ENABLE
641         if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
642 #endif
643         add_key(KC_NUMLOCK);
644         send_keyboard_report();
645         del_key(KC_NUMLOCK);
646         send_keyboard_report();
647     }
648
649     else if (KC_LOCKING_SCROLL == code) {
650 #ifdef LOCKING_RESYNC_ENABLE
651         if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
652 #endif
653         add_key(KC_SCROLLLOCK);
654         send_keyboard_report();
655         del_key(KC_SCROLLLOCK);
656         send_keyboard_report();
657     }
658 #endif
659
660     else if IS_KEY(code) {
661         del_key(code);
662         send_keyboard_report();
663     }
664     else if IS_MOD(code) {
665         del_mods(MOD_BIT(code));
666         send_keyboard_report();
667     }
668     else if IS_SYSTEM(code) {
669         host_system_send(0);
670     }
671     else if IS_CONSUMER(code) {
672         host_consumer_send(0);
673     }
674 }
675
676 void register_mods(uint8_t mods)
677 {
678     if (mods) {
679         add_mods(mods);
680         send_keyboard_report();
681     }
682 }
683
684 void unregister_mods(uint8_t mods)
685 {
686     if (mods) {
687         del_mods(mods);
688         send_keyboard_report();
689     }
690 }
691
692 void clear_keyboard(void)
693 {
694     clear_mods();
695     clear_keyboard_but_mods();
696 }
697
698 void clear_keyboard_but_mods(void)
699 {
700     clear_weak_mods();
701     clear_macro_mods();
702     clear_keys();
703     send_keyboard_report();
704 #ifdef MOUSEKEY_ENABLE
705     mousekey_clear();
706     mousekey_send();
707 #endif
708 #ifdef EXTRAKEY_ENABLE
709     host_system_send(0);
710     host_consumer_send(0);
711 #endif
712 }
713
714 bool is_tap_key(keypos_t key)
715 {
716     action_t action = layer_switch_get_action(key);
717
718     switch (action.kind.id) {
719         case ACT_LMODS_TAP:
720         case ACT_RMODS_TAP:
721         case ACT_LAYER_TAP:
722         case ACT_LAYER_TAP_EXT:
723             switch (action.layer_tap.code) {
724                 case 0x00 ... 0xdf:
725                 case OP_TAP_TOGGLE:
726                 case OP_ONESHOT:
727                     return true;
728             }
729             return false;
730         case ACT_SWAP_HANDS:
731             switch (action.swap.code) {
732                 case 0x00 ... 0xdf:
733                 case OP_SH_TAP_TOGGLE:
734                     return true;
735             }
736             return false;
737         case ACT_MACRO:
738         case ACT_FUNCTION:
739             if (action.func.opt & FUNC_TAP) { return true; }
740             return false;
741     }
742     return false;
743 }
744
745
746 /*
747  * debug print
748  */
749 void debug_event(keyevent_t event)
750 {
751     dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
752 }
753
754 void debug_record(keyrecord_t record)
755 {
756     debug_event(record.event);
757 #ifndef NO_ACTION_TAPPING
758     dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
759 #endif
760 }
761
762 void debug_action(action_t action)
763 {
764     switch (action.kind.id) {
765         case ACT_LMODS:             dprint("ACT_LMODS");             break;
766         case ACT_RMODS:             dprint("ACT_RMODS");             break;
767         case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
768         case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
769         case ACT_USAGE:             dprint("ACT_USAGE");             break;
770         case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
771         case ACT_LAYER:             dprint("ACT_LAYER");             break;
772         case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
773         case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
774         case ACT_MACRO:             dprint("ACT_MACRO");             break;
775         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
776         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
777         case ACT_SWAP_HANDS:        dprint("ACT_SWAP_HANDS");        break;
778         default:                    dprint("UNKNOWN");               break;
779     }
780     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
781 }