diff options
| -rw-r--r-- | vis-cmds.c | 4 | ||||
| -rw-r--r-- | vis-core.h | 1 | ||||
| -rw-r--r-- | vis-lua.c | 10 | ||||
| -rw-r--r-- | vis-modes.c | 29 | ||||
| -rw-r--r-- | vis.c | 4 | ||||
| -rw-r--r-- | vis.h | 3 |
6 files changed, 44 insertions, 7 deletions
@@ -791,7 +791,7 @@ static bool cmd_map(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor const char *lhs = argv[2]; char *rhs = strdup(argv[3]); - if (!rhs || !(binding = calloc(1, sizeof *binding))) + if (!rhs || !(binding = vis_binding_new(vis))) goto err; binding->alias = rhs; @@ -804,7 +804,7 @@ static bool cmd_map(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor err: if (!mapped) { free(rhs); - free(binding); + vis_binding_free(vis, binding); } return mapped; } @@ -188,6 +188,7 @@ struct Vis { VisEvent *event; Array motions; Array textobjects; + Array bindings; }; enum VisEvents { @@ -669,8 +669,11 @@ static int keymap(lua_State *L, Vis *vis, Win *win) { if (!key || !lua_isfunction(L, 4)) goto err; const char *help = luaL_optstring(L, 5, NULL); - if (!(binding = calloc(1, sizeof *binding)) || !(action = calloc(1, sizeof *action))) + if (!(binding = vis_binding_new(vis))) goto err; + if (!(action = calloc(1, sizeof *action))) + goto err; + binding->action = action; /* store reference to function in the registry */ lua_pushvalue(L, 4); @@ -687,8 +690,6 @@ static int keymap(lua_State *L, Vis *vis, Win *win) { }, }; - binding->action = action; - if (win) { if (!vis_window_mode_map(win, mode, true, key, binding)) goto err; @@ -700,8 +701,7 @@ static int keymap(lua_State *L, Vis *vis, Win *win) { lua_pushboolean(L, true); return 1; err: - free(binding); - free(action); + vis_binding_free(vis, binding); lua_pushboolean(L, false); return 1; } diff --git a/vis-modes.c b/vis-modes.c index 7008161..68771ce 100644 --- a/vis-modes.c +++ b/vis-modes.c @@ -2,6 +2,35 @@ #include "vis-core.h" #include "util.h" +KeyBinding *vis_binding_new(Vis *vis) { + KeyBinding *binding = calloc(1, sizeof *binding); + if (binding && array_add_ptr(&vis->bindings, binding)) + return binding; + free(binding); + return NULL; +} + +void vis_binding_free(Vis *vis, KeyBinding *binding) { + if (!binding) + return; + size_t len = array_length(&vis->bindings); + for (size_t i = 0; i < len; i++) { + if (binding == array_get_ptr(&vis->bindings, i)) { + if (binding->alias) + free((char*)binding->alias); + const KeyAction *action = binding->action; + if (action) { + free((char*)action->name); + free((char*)action->help); + free((KeyAction*)action); + } + free(binding); + array_remove(&vis->bindings, i); + break; + } + } +} + static Mode *mode_get(Vis *vis, enum VisMode mode) { if (mode < LENGTH(vis_modes)) return &vis_modes[mode]; @@ -510,6 +510,7 @@ Vis *vis_new(Ui *ui, VisEvent *event) { vis->registers[VIS_REG_CLIPBOARD].type = REGISTER_CLIPBOARD; array_init(&vis->motions); array_init(&vis->textobjects); + array_init(&vis->bindings); action_reset(&vis->action); buffer_init(&vis->input_queue); vis->keys = &vis->input_queue; @@ -570,6 +571,9 @@ void vis_free(Vis *vis) { map_free(vis_modes[i].bindings); array_release_full(&vis->motions); array_release_full(&vis->textobjects); + while (array_length(&vis->bindings)) + vis_binding_free(vis, array_get_ptr(&vis->bindings, 0)); + array_release(&vis->bindings); free(vis->shell); free(vis); } @@ -152,6 +152,9 @@ void vis_exit(Vis*, int status); /* emergency exit, print given message, perform minimal ui cleanup and exit process */ void vis_die(Vis*, const char *msg, ...) __attribute__((noreturn,format(printf, 2, 3))); +KeyBinding *vis_binding_new(Vis*); +void vis_binding_free(Vis*, KeyBinding*); + enum VisMode { VIS_MODE_NORMAL, VIS_MODE_OPERATOR_PENDING, |
