diff --git a/src/Kaleidoscope.cpp b/src/Kaleidoscope.cpp index 8718da3d..4275934c 100644 --- a/src/Kaleidoscope.cpp +++ b/src/Kaleidoscope.cpp @@ -1,8 +1,8 @@ #include "Kaleidoscope.h" #include -Kaleidoscope_::eventHandlerHook Kaleidoscope_::eventHandlers[HOOK_MAX]; -Kaleidoscope_::loopHook Kaleidoscope_::loopHooks[HOOK_MAX]; +Kaleidoscope_::listItem *Kaleidoscope_::eventHandlerRootNode; +Kaleidoscope_::listItem *Kaleidoscope_::loopHookRootNode; Kaleidoscope_::Kaleidoscope_(void) { } @@ -20,10 +20,12 @@ Kaleidoscope_::setup(void) { void Kaleidoscope_::runLoopHooks (bool postClear) { - for (byte i = 0; loopHooks[i] != NULL && i < HOOK_MAX; i++) { - loopHook hook = loopHooks[i]; - (*hook)(postClear); - } + auto *node = loopHookRootNode; + + while (node) { + (*(node->hook))(postClear); + node = node->next; + } } void @@ -51,52 +53,57 @@ Kaleidoscope_::use(KaleidoscopePlugin *plugin, ...) { va_end(ap); } -void -Kaleidoscope_::replaceEventHandlerHook(eventHandlerHook oldHook, eventHandlerHook newHook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (eventHandlers[i] == oldHook) { - eventHandlers[i] = newHook; - return; +template +void Kaleidoscope_::appendHook(T **rootNode, T *newNode) { + if (!*rootNode) { + *rootNode = newNode; + return; + } + + T *node = *rootNode; + + while (node->next) { + node = node->next; } - } + node->next = newNode; } +template void -Kaleidoscope_::appendEventHandlerHook (eventHandlerHook hook) { - replaceEventHandlerHook((eventHandlerHook)NULL, hook); +Kaleidoscope_::useHook(T **rootNode, T *newNode) { + if (!*rootNode) { + *rootNode = newNode; + return; + } + + T *node = *rootNode; + + while (node->next) { + if (node->hook == newNode->hook) + return; + node = node->next; + } + node->next = newNode; } void -Kaleidoscope_::useEventHandlerHook (eventHandlerHook hook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (eventHandlers[i] == hook) - return; - } - appendEventHandlerHook(hook); +Kaleidoscope_::useHook(listItem *newNode) { + useHook(&eventHandlerRootNode, newNode); } void -Kaleidoscope_::replaceLoopHook(loopHook oldHook, loopHook newHook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (loopHooks[i] == oldHook) { - loopHooks[i] = newHook; - return; - } - } +Kaleidoscope_::useHook(listItem *newNode) { + useHook(&loopHookRootNode, newNode); } void -Kaleidoscope_::appendLoopHook(loopHook hook) { - replaceLoopHook((loopHook)NULL, hook); +Kaleidoscope_::appendHook(listItem *newNode) { + appendHook(&eventHandlerRootNode, newNode); } void -Kaleidoscope_::useLoopHook(loopHook hook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (loopHooks[i] == hook) - return; - } - appendLoopHook (hook); +Kaleidoscope_::appendHook(listItem *newNode) { + appendHook(&loopHookRootNode, newNode); } Kaleidoscope_ Kaleidoscope; diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index c79d6f6e..5453290e 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -24,8 +24,6 @@ void setup(); #include "key_events.h" #include "layers.h" -#define HOOK_MAX 64 - extern HARDWARE_IMPLEMENTATION KeyboardHardware; #ifndef VERSION @@ -53,20 +51,32 @@ extern HARDWARE_IMPLEMENTATION KeyboardHardware; }) class KaleidoscopePlugin { - public: - virtual void begin(void) = 0; + public: + virtual void begin(void) = 0; }; class Kaleidoscope_ { public: Kaleidoscope_(void); - void setup(const byte keymap_count) { setup(); }; + void setup(const byte keymap_count) { + setup(); + }; void setup(void); void loop(void); void use(KaleidoscopePlugin *plugin, ...) __attribute__((sentinel)); // ---- hooks ---- + typedef Key (*eventHandlerHook)(Key mappedKey, byte row, byte col, uint8_t keyState); + typedef void (*loopHook)(bool postClear); + + template struct listItem { + T hook; + listItem *next; + }; + + static listItem *eventHandlerRootNode; + static listItem *loopHookRootNode; /* * In most cases, one only wants a single copy of a hook. On the other hand, @@ -75,38 +85,43 @@ class Kaleidoscope_ { * plugins too. In case the end-user calls the same setup function, we'd end up * with hooks registered multiple times. * - * To avoid this, protection against double-registration has been introduced. - * The `event_handler_hook_use` and `loop_hook_use` functions will only allow - * one copy of the hook. The `event_handler_hook_append` and `loop_hook_append` - * functions will, on the other hand, just append the hooks, and not care about - * protection. + * To avoid this, protection against double-registration has been + * introduced. The `useHook` functions will only allow one copy of the hook. + * The `appendHook` functions will, on the other hand, just append the + * hooks, and not care about protection. */ - typedef Key (*eventHandlerHook)(Key mappedKey, byte row, byte col, uint8_t keyState); - static eventHandlerHook eventHandlers[HOOK_MAX]; - - static void replaceEventHandlerHook(eventHandlerHook oldHook, eventHandlerHook newHook); - static void appendEventHandlerHook(eventHandlerHook hook); - static void useEventHandlerHook(eventHandlerHook hook); - - typedef void (*loopHook)(bool postClear); - static loopHook loopHooks[HOOK_MAX]; + static void appendHook(listItem *newNode); + static void appendHook(listItem *newNode); + static void useHook(listItem *newNode); + static void useHook(listItem *newNode); - static void replaceLoopHook(loopHook oldHook, loopHook newHook); - static void appendLoopHook(loopHook hook); - static void useLoopHook(loopHook hook); + private: + template static void appendHook(T **rootNode, T *newNode); + template static void useHook(T **rootNode, T *newNode); - private: static void runLoopHooks(bool postClear); }; extern Kaleidoscope_ Kaleidoscope; -/* -- DEPRECATED aliases; remove them when there are no more users. -- */ - -#define event_handler_hook_use(hook) Kaleidoscope.useEventHandlerHook(hook); -#define event_handler_hook_append(hook) Kaleidoscope.appendEventHandlerHook(hook) -#define event_handler_hook_replace(oldHook, newHook) Kaleidoscope.replaceEventHandlerHook(oldHook, newHook) - -#define loop_hook_use(hook) Kaleidoscope.useLoopHook(hook) -#define loop_hook_append(hook) Kaleidoscope.appendLoopHook(hook) -#define loop_hook_replace(oldHook, newHook) Kaleidoscope.replaceLoopHook(oldHook, newHook) +#define event_handler_hook_use(hook) { \ + static Kaleidoscope_::listItem \ + eventHandlerHookNode = {&hook, NULL}; \ + Kaleidoscope.useHook(&eventHandlerHookNode); \ + } +#define event_handler_hook_append(hook) { \ + static Kaleidoscope_::listItem \ + eventHandlerHookNode = {&hook, NULL}; \ + Kaleidoscope.appendHook(&eventHandlerHookNode); \ + } + +#define loop_hook_use(hook) { \ + static Kaleidoscope_::listItem \ + loopHookNode = {&hook, NULL}; \ + Kaleidoscope.useHook(&loopHookNode); \ + } +#define loop_hook_append(hook) { \ + static Kaleidoscope_::listItem \ + loopHookNode = {&hook, NULL}; \ + Kaleidoscope.appendHook(&loopHookNode); \ + } diff --git a/src/key_events.cpp b/src/key_events.cpp index 38a7cc0a..27340ab8 100644 --- a/src/key_events.cpp +++ b/src/key_events.cpp @@ -80,12 +80,16 @@ void handle_key_event(Key mappedKey, byte row, byte col, uint8_t keyState) { if (!(keyState & INJECTED)) { mappedKey = Layer.lookup(row, col); } - for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) { - Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i]; - mappedKey = (*handler)(mappedKey, row, col, keyState); - if (mappedKey.raw == Key_NoKey.raw) + + auto *node = Kaleidoscope.eventHandlerRootNode; + + while (node) { + mappedKey = (*(node->hook))(mappedKey, row, col, keyState); + if (mappedKey == Key_NoKey) return; + node = node->next; } + mappedKey = Layer.eventHandler(mappedKey, row, col, keyState); if (mappedKey.raw == Key_NoKey.raw) return;