diff --git a/parser/parser.c b/parser/parser.c index 9224bb7..84a9095 100644 --- a/parser/parser.c +++ b/parser/parser.c @@ -4,6 +4,7 @@ * but you get the idea */ #include "parser.h" +#include "util.h" #include #include @@ -361,10 +362,18 @@ parse_keybinds(lua_State *L, Config *cfg) cfg->nkeybinds = 0; int n = (int)lua_rawlen(L, -1); - for (int i = 1; i <= n && cfg->nkeybinds < CFG_MAX_KEYBINDS; i++) { + for (int i = 1; i <= n; i++) { lua_rawgeti(L, -1, i); if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } + while (cfg->nkeybinds >= cfg->keybinds_cap) { + cfg->keybinds_cap *= 2; + cfg->keybinds = realloc(cfg->keybinds, + cfg->keybinds_cap * sizeof(CfgKeybind)); + memset(cfg->keybinds + cfg->nkeybinds, 0, + (cfg->keybinds_cap - cfg->nkeybinds) * sizeof(CfgKeybind)); + } + CfgKeybind *kb = &cfg->keybinds[cfg->nkeybinds]; memset(kb, 0, sizeof(*kb)); @@ -429,10 +438,18 @@ parse_buttons(lua_State *L, Config *cfg) cfg->nbuttons = 0; int n = (int)lua_rawlen(L, -1); - for (int i = 1; i <= n && cfg->nbuttons < CFG_MAX_KEYBINDS; i++) { + for (int i = 1; i <= n; i++) { lua_rawgeti(L, -1, i); if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } + while (cfg->nbuttons >= cfg->buttons_cap) { + cfg->buttons_cap *= 2; + cfg->buttons = realloc(cfg->buttons, + cfg->buttons_cap * sizeof(CfgButton)); + memset(cfg->buttons + cfg->nbuttons, 0, + (cfg->buttons_cap - cfg->nbuttons) * sizeof(CfgButton)); + } + CfgButton *b = &cfg->buttons[cfg->nbuttons++]; memset(b, 0, sizeof(*b)); @@ -509,10 +526,18 @@ parse_scrolls(lua_State *L, Config *cfg) cfg->nscrolls = 0; int n = (int)lua_rawlen(L, -1); - for (int i = 1; i <= n && cfg->nscrolls < CFG_MAX_KEYBINDS; i++) { + for (int i = 1; i <= n; i++) { lua_rawgeti(L, -1, i); if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } + while (cfg->nscrolls >= cfg->scrolls_cap) { + cfg->scrolls_cap *= 2; + cfg->scrolls = realloc(cfg->scrolls, + cfg->scrolls_cap * sizeof(CfgScroll)); + memset(cfg->scrolls + cfg->nscrolls, 0, + (cfg->scrolls_cap - cfg->nscrolls) * sizeof(CfgScroll)); + } + CfgScroll *s = &cfg->scrolls[cfg->nscrolls]; memset(s, 0, sizeof(*s)); s->source = -1; @@ -742,16 +767,24 @@ config_load(const char *path, Config *cfg) parse_rules (L, cfg); parse_monitors (L, cfg); parse_workspace_layouts(L, cfg); + cfg->keybinds = ecalloc(16, sizeof(CfgKeybind)); + cfg->keybinds_cap = 16; parse_keybinds (L, cfg); if (cfg->nkeybinds >= CFG_MAX_KEYBINDS) fprintf(stderr, "peachwm config: number of keybinds reached the limit (%d). " "Increase CFG_MAX_KEYBINDS or remove some binds.\n", CFG_MAX_KEYBINDS); + + cfg->buttons = ecalloc(16, sizeof(CfgButton)); + cfg->buttons_cap = 16; parse_buttons (L, cfg); if (cfg->nbuttons >= CFG_MAX_KEYBINDS) fprintf(stderr, "peachwm config: number of button binds reached the limit (%d). " "Increase CFG_MAX_KEYBINDS or remove some binds.\n", CFG_MAX_KEYBINDS); + + cfg->scrolls = ecalloc(16, sizeof(CfgScroll)); + cfg->scrolls_cap = 16; parse_scrolls (L, cfg); if (cfg->nscrolls >= CFG_MAX_KEYBINDS) fprintf(stderr, "peachwm config: number of scroll binds reached the limit (%d). " diff --git a/parser/parser.h b/parser/parser.h index 41abf92..0d3248c 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -143,14 +143,17 @@ typedef struct { CfgMonitorRule monitors[CFG_MAX_MONITORS]; int nmonitors; - CfgKeybind keybinds[CFG_MAX_KEYBINDS]; + CfgKeybind *keybinds; int nkeybinds; + int keybinds_cap; - CfgButton buttons[CFG_MAX_KEYBINDS]; + CfgButton *buttons; int nbuttons; + int buttons_cap; - CfgScroll scrolls[CFG_MAX_KEYBINDS]; + CfgScroll *scrolls; int nscrolls; + int scrolls_cap; bool sloppyfocus; bool bypass_surface_visibility; diff --git a/peachwm b/peachwm index ed7c25e..a9452af 100755 Binary files a/peachwm and b/peachwm differ diff --git a/src/peachwm.c b/src/peachwm.c index 0a1a326..5011455 100644 --- a/src/peachwm.c +++ b/src/peachwm.c @@ -3231,7 +3231,19 @@ on_config_reload(const Config *newcfg, void *ud) Monitor *m; (void)ud; reapply_input_config(newcfg); + + /* Free old dynamic arrays, then deep-copy new in. + * Zero source pointers so watch_dispatch's calloc'd Config + * can be freed without double-freeing the arrays we now own. */ + free(cfg.keybinds); + free(cfg.buttons); + free(cfg.scrolls); cfg = *newcfg; + Config *nc = (Config *)newcfg; + nc->keybinds = NULL; + nc->buttons = NULL; + nc->scrolls = NULL; + reapply_monitor_config(); reapply_client_appearance(); reapply_client_rules(); @@ -3252,7 +3264,16 @@ do_reload(void) if (config_load(config_path, &fresh) == 0) { fprintf(stderr, "peachwm: config reloaded via IPC\n"); reapply_input_config(&fresh); + + /* Free old dynamic arrays, copy fresh in, zero source */ + free(cfg.keybinds); + free(cfg.buttons); + free(cfg.scrolls); cfg = fresh; + fresh.keybinds = NULL; + fresh.buttons = NULL; + fresh.scrolls = NULL; + reapply_monitor_config(); reapply_client_appearance(); reapply_client_rules();