Skip to content

Commit e21b9b1

Browse files
Merge branch 'fossillogic:main' into main
2 parents 164d610 + 6ca5162 commit e21b9b1

File tree

6 files changed

+454
-7
lines changed

6 files changed

+454
-7
lines changed

.github/workflows/meson_ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
shell: pwsh
3333
run: |
3434
python -m pip install --upgrade pip
35-
python -m pip install meson==1.8.0 ninja
35+
python -m pip install meson ninja
3636
if ($env:msvc_version -eq "2019") {
3737
choco install visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --includeOptional --passive"
3838
} elseif ($env:msvc_version -eq "2022") {
@@ -75,7 +75,7 @@ jobs:
7575

7676
- name: Install Meson, Ninja
7777
run: |
78-
python -m pip install meson==1.8.0 ninja
78+
python -m pip install meson ninja
7979
8080
- name: Configure
8181
run: OBJC=clang OBJCXX=clang++ meson setup builddir --fatal-meson-warnings -Dwerror=true -Dwith_test=enabled -Dwarning_level=3
@@ -122,7 +122,7 @@ jobs:
122122

123123
- name: Install Meson and Ninja
124124
run: |
125-
python -m pip install meson==1.8.0 ninja
125+
python -m pip install meson ninja
126126
127127
- name: Configure
128128
run: meson setup builddir --fatal-meson-warnings -Dwerror=true -Dwith_test=enabled -Dwarning_level=3
@@ -163,7 +163,7 @@ jobs:
163163

164164
- name: Install Meson and Ninja
165165
run: |
166-
python -m pip install meson==1.8.0 ninja
166+
python -m pip install meson ninja
167167
168168
- name: Configure
169169
run: meson setup builddir --fatal-meson-warnings -Dwerror=true -Dwith_test=enabled -Dwarning_level=3
@@ -211,4 +211,4 @@ jobs:
211211
/bin/bash -c "
212212
sudo apt update
213213
meson setup builddir --fatal-meson-warnings -Dwerror=true -Dwith_test=enabled -Dwarning_level=3
214-
meson test -C builddir -v --test-args='show --mode tree --verbose ci --result fail'"
214+
meson test -C builddir -v --test-args='show --mode tree --verbose ci --result fail'"

code/logic/fossil/io/input.h

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,85 @@ void fossil_io_show_progress(int progress);
172172
*/
173173
int fossil_io_gets(char *buffer, size_t size);
174174

175+
/**
176+
* @brief Type for representing a key binding.
177+
*/
178+
typedef void (*fossil_io_action_callback_t)(void);
179+
180+
typedef struct {
181+
int key_code; /**< The integer key code (e.g., ASCII or special code). */
182+
const char *action; /**< The action string associated with this key. */
183+
fossil_io_action_callback_t callback; /**< Optional function to call when key is pressed. */
184+
} fossil_io_keybinding_t;
185+
186+
/**
187+
* @brief Registers a new key binding.
188+
*
189+
* Adds a key-action mapping to the input library.
190+
*
191+
* @param key_code The integer key code to bind.
192+
* @param action The action string associated with the key.
193+
* @return 0 on success, non-zero on failure (e.g., duplicate key).
194+
*/
195+
int fossil_io_register_keybinding(int key_code, const char *action);
196+
197+
/**
198+
* @brief Removes an existing key binding.
199+
*
200+
* @param key_code The key code of the binding to remove.
201+
* @return 0 on success, non-zero if the key was not found.
202+
*/
203+
int fossil_io_unregister_keybinding(int key_code);
204+
205+
/**
206+
* Registers a new key binding with optional callback.
207+
*/
208+
int fossil_io_register_keybinding_with_callback(int key_code, const char *action, fossil_io_action_callback_t cb);
209+
210+
/**
211+
* @brief Retrieves the action associated with a key code.
212+
*
213+
* @param key_code The key code to look up.
214+
* @return The action string if found, NULL otherwise.
215+
*/
216+
const char* fossil_io_get_keybinding_action(int key_code);
217+
218+
/**
219+
* @brief Processes a key event.
220+
*
221+
* Checks if a key has a registered action and triggers it if found.
222+
*
223+
* @param key_code The key code that was pressed.
224+
* @return 1 if an action was triggered, 0 if no binding exists.
225+
*/
226+
int fossil_io_process_keybinding(int key_code);
227+
228+
/**
229+
* @brief Lists all currently registered key bindings.
230+
*
231+
* @param bindings Array of fossil_io_keybinding_t to populate.
232+
* @param max_bindings Maximum number of bindings to populate.
233+
* @return Number of bindings populated in the array.
234+
*/
235+
size_t fossil_io_list_keybindings(fossil_io_keybinding_t *bindings, size_t max_bindings);
236+
237+
/**
238+
* @brief Clears all registered key bindings.
239+
*
240+
* Frees any internal memory and removes all key-action mappings.
241+
*/
242+
void fossil_io_clear_keybindings(void);
243+
175244
#ifdef __cplusplus
176245
}
177246

247+
#include <cstddef>
248+
#include <string>
249+
#include <vector>
250+
#include <utility>
251+
#include <cstdarg>
252+
#include <istream>
253+
178254
/**
179255
* Namespace for the Fossil Logic I/O library.
180256
*/
@@ -397,6 +473,82 @@ namespace fossil {
397473
return input_stream;
398474
}
399475

476+
/**
477+
* Registers a key binding with an associated action string.
478+
*
479+
* @param key_code The integer key code.
480+
* @param action The action string to associate with the key.
481+
* @return 0 on success, non-zero on failure.
482+
*/
483+
static int register_keybinding(int key_code, const std::string &action) {
484+
return fossil_io_register_keybinding(key_code, action.c_str());
485+
}
486+
487+
/**
488+
* Registers a key binding with an optional callback function.
489+
*
490+
* @param key_code The integer key code.
491+
* @param action The action string to associate with the key.
492+
* @param callback Function pointer to execute when the key is pressed.
493+
* @return 0 on success, non-zero on failure.
494+
*/
495+
static int register_keybinding_callback(int key_code, const std::string &action, void (*callback)()) {
496+
return fossil_io_register_keybinding_with_callback(key_code, action.c_str(), callback);
497+
}
498+
499+
/**
500+
* Unregisters a key binding.
501+
*
502+
* @param key_code The key code of the binding to remove.
503+
* @return 0 on success, non-zero if the key was not found.
504+
*/
505+
static int unregister_keybinding(int key_code) {
506+
return fossil_io_unregister_keybinding(key_code);
507+
}
508+
509+
/**
510+
* Processes a key event.
511+
*
512+
* @param key_code The key code to process.
513+
* @return 1 if an action was triggered, 0 if no binding exists.
514+
*/
515+
static int process_keybinding(int key_code) {
516+
return fossil_io_process_keybinding(key_code);
517+
}
518+
519+
/**
520+
* Retrieves the action associated with a key code.
521+
*
522+
* @param key_code The key code to look up.
523+
* @return The action string if found, empty string otherwise.
524+
*/
525+
static std::string get_keybinding_action(int key_code) {
526+
const char *action = fossil_io_get_keybinding_action(key_code);
527+
return action ? std::string(action) : std::string();
528+
}
529+
530+
/**
531+
* Lists all registered key bindings.
532+
*
533+
* @return A vector of key-action pairs representing all bindings.
534+
*/
535+
static std::vector<std::pair<int, std::string>> list_keybindings() {
536+
std::vector<std::pair<int, std::string>> bindings;
537+
fossil_io_keybinding_t arr[256];
538+
size_t count = fossil_io_list_keybindings(arr, 256);
539+
for (size_t i = 0; i < count; i++) {
540+
bindings.emplace_back(arr[i].key_code, arr[i].action ? arr[i].action : "");
541+
}
542+
return bindings;
543+
}
544+
545+
/**
546+
* Clears all registered key bindings.
547+
*/
548+
static void clear_keybindings() {
549+
fossil_io_clear_keybindings();
550+
}
551+
400552
};
401553

402554
}

code/logic/input.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
#include "fossil/io/input.h"
1515
#include "fossil/io/output.h"
16+
#include "fossil/io/cstring.h"
1617

1718
#include <ctype.h>
1819
#include <stdio.h>
@@ -315,3 +316,100 @@ int fossil_io_gets(char *buffer, size_t size) {
315316
}
316317
return 0; // Success
317318
}
319+
320+
#define MAX_KEYBINDINGS 256
321+
static fossil_io_keybinding_t _keybindings[MAX_KEYBINDINGS];
322+
static size_t _num_keybindings = 0;
323+
324+
int fossil_io_register_keybinding(int key_code, const char *action) {
325+
if (!action || _num_keybindings >= MAX_KEYBINDINGS) return 1;
326+
327+
// Check for duplicate
328+
for (size_t i = 0; i < _num_keybindings; i++) {
329+
if (_keybindings[i].key_code == key_code) return 2; // Duplicate key
330+
}
331+
332+
_keybindings[_num_keybindings].key_code = key_code;
333+
_keybindings[_num_keybindings].action = fossil_io_cstring_dup(action);
334+
if (!_keybindings[_num_keybindings].action) return 3; // Allocation failure
335+
336+
_num_keybindings++;
337+
return 0;
338+
}
339+
340+
int fossil_io_unregister_keybinding(int key_code) {
341+
for (size_t i = 0; i < _num_keybindings; i++) {
342+
if (_keybindings[i].key_code == key_code) {
343+
free((void*)_keybindings[i].action);
344+
// Shift remaining bindings
345+
for (size_t j = i; j < _num_keybindings - 1; j++) {
346+
_keybindings[j] = _keybindings[j + 1];
347+
}
348+
_num_keybindings--;
349+
return 0;
350+
}
351+
}
352+
return 1; // Key not found
353+
}
354+
355+
const char* fossil_io_get_keybinding_action(int key_code) {
356+
for (size_t i = 0; i < _num_keybindings; i++) {
357+
if (_keybindings[i].key_code == key_code) {
358+
return _keybindings[i].action;
359+
}
360+
}
361+
return NULL;
362+
}
363+
364+
/**
365+
* Registers a new key binding with optional callback.
366+
*/
367+
int fossil_io_register_keybinding_with_callback(int key_code, const char *action, fossil_io_action_callback_t cb) {
368+
if (!action || _num_keybindings >= MAX_KEYBINDINGS) return 1;
369+
370+
// Check for duplicate key
371+
for (size_t i = 0; i < _num_keybindings; i++) {
372+
if (_keybindings[i].key_code == key_code) return 2; // Duplicate
373+
}
374+
375+
_keybindings[_num_keybindings].key_code = key_code;
376+
_keybindings[_num_keybindings].action = fossil_io_cstring_dup(action);
377+
_keybindings[_num_keybindings].callback = cb;
378+
if (!_keybindings[_num_keybindings].action) return 3; // Allocation failed
379+
380+
_num_keybindings++;
381+
return 0;
382+
}
383+
384+
/**
385+
* Enhanced key processing that calls registered callback.
386+
*/
387+
int fossil_io_process_keybinding(int key_code) {
388+
for (size_t i = 0; i < _num_keybindings; i++) {
389+
if (_keybindings[i].key_code == key_code) {
390+
if (_keybindings[i].callback) {
391+
_keybindings[i].callback(); // Execute callback
392+
} else {
393+
printf("Action triggered: %s\n", _keybindings[i].action);
394+
}
395+
return 1; // Action processed
396+
}
397+
}
398+
return 0; // No binding
399+
}
400+
401+
size_t fossil_io_list_keybindings(fossil_io_keybinding_t *bindings, size_t max_bindings) {
402+
size_t count = (max_bindings < _num_keybindings) ? max_bindings : _num_keybindings;
403+
for (size_t i = 0; i < count; i++) {
404+
bindings[i].key_code = _keybindings[i].key_code;
405+
bindings[i].action = _keybindings[i].action;
406+
}
407+
return count;
408+
}
409+
410+
void fossil_io_clear_keybindings(void) {
411+
for (size_t i = 0; i < _num_keybindings; i++) {
412+
free((void*)_keybindings[i].action);
413+
}
414+
_num_keybindings = 0;
415+
}

0 commit comments

Comments
 (0)