From 0d1f4776521b286cb7c0091ac5bcd659cdc87132 Mon Sep 17 00:00:00 2001 From: papush! Date: Fri, 4 Jul 2025 23:21:14 +0200 Subject: add multikey binds support --- src/bindings_file.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/bindings_file.c (limited to 'src/bindings_file.c') diff --git a/src/bindings_file.c b/src/bindings_file.c new file mode 100644 index 0000000..4eab11f --- /dev/null +++ b/src/bindings_file.c @@ -0,0 +1,128 @@ +#include "bindings_file.h" +#include "binding.h" + +#include +#include +#include +#include +#include + + +struct binding *bindings = NULL; +size_t nbindings = 0; + +void skip_space(char **c) +{ + for (; **c && isspace(**c); (*c)++); +} + +int read_int(char **c, int out[static 1]) +{ + if (!isdigit(**c)) + { + return -1; + } + errno = 0; + char *end = NULL; + *out = strtol(*c, &end, 10); + if (errno) + { + return -1; + } + *c = end; + return 0; +} + +void parse_bindings_file(const char path[static 1]) +{ + size_t cap = 512; + bindings = malloc(sizeof (struct binding) * cap); + FILE *f = fopen(path, "r"); + if (f == NULL) + { + fprintf(stderr, "failed to open bindings file: %s: %s\n", path, + strerror(errno)); + exit(EXIT_FAILURE); + } + + size_t line_nb = 0; + char *line = NULL; + size_t n; + while (getline(&line, &n, f) != -1) + { + line_nb++; + struct binding binding = {0}; + char *end = strchr(line, '#'); + if (end == NULL) + { + end = line + strlen(line); + } + *end = '\0'; + char *c = line; + + skip_space(&c); + if (c == end) continue; + + /* code */ + int code; + for (;;) + { + if (read_int(&c, &code) < 0 || c >= end) + { + goto fail; + } + set_key(binding.keys, code); + if (*c++ != '+') + { + c--; + break; + } + } + + /* press | release */ + skip_space(&c); + if (strncmp(c, "press", strlen("press")) == 0) + { + c += strlen("press"); + binding.value = PRESSED; + } + else if (strncmp(c, "release", strlen("release")) == 0) + { + c += strlen("release"); + binding.value = RELEASED; + } + else + { + goto fail; + } + + /* cmd */ + skip_space(&c); + if (c >= end) + { + goto fail; + } + binding.cmd = malloc(end - c + 1); + memcpy(binding.cmd, c, end - c + 1); + + if (nbindings >= cap) + { + cap *= 2; + bindings = realloc(bindings, cap * sizeof (struct binding)); + } + bindings[nbindings++] = binding; + } + if (!feof(f)) + { + fprintf(stderr, "failed to read bindings file: %s: %s\n", path, + strerror(errno)); + } + free(line); + fclose(f); + return; + +fail: + fprintf(stderr, "syntax error at line %ld\n", line_nb); + exit(EXIT_FAILURE); +} + -- cgit v1.2.3-70-g09d2