From 12efa0e3b429675047cb2900d49e1f38afeb650b Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Sat, 18 Sep 2021 12:27:12 -0700 Subject: [PATCH] Add ability to bind arbitrary functions. Before all the predated commands where kept in an array and their indexes were used in bindings. This meant that users couldn't add their own functions from the config file. Now key/mouse bindings have been changed to to store the function ptr (wrapped in a cmd_t struct to also store the mode) directly instead. General cleanup done in this commit: Defined `MODE_ALL` instead of using magic number. For example, suppose one had bindings like: { 0, XK_q, g_quit, None }, { ShitMask, XK_q, {quit_err}, None } { ControlMask, XK_q, {quit_err, .mode=MODE_IMAGE}, None } The existing binding `q` has been left unchanged and is defined the same way. However, the new hypothetical binding `Shift-q` can be used to call the custom function quit_err in any mode (default). `Ctrl-q` on the other hand will be called only on image mode. Closes #50 --- Makefile | 2 +- commands.c | 12 -------- commands.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ commands.lst | 36 ----------------------- main.c | 15 +++++----- nsxiv.h | 18 +++--------- 6 files changed, 96 insertions(+), 70 deletions(-) create mode 100644 commands.h delete mode 100644 commands.lst diff --git a/Makefile b/Makefile index caf72f5..be93097 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ nsxiv: $(OBJS) @echo "CC $@" $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< -$(OBJS): Makefile nsxiv.h commands.lst config.h +$(OBJS): Makefile nsxiv.h config.h options.o: version.h window.o: icon/data.h diff --git a/commands.c b/commands.c index 3981f0f..e52b381 100644 --- a/commands.c +++ b/commands.c @@ -436,15 +436,3 @@ bool ct_reload_all(arg_t _) tns.dirty = true; return true; } - - -#undef G_CMD -#define G_CMD(c) { -1, cg_##c }, -#undef I_CMD -#define I_CMD(c) { MODE_IMAGE, ci_##c }, -#undef T_CMD -#define T_CMD(c) { MODE_THUMB, ct_##c }, - -const cmd_t cmds[CMD_COUNT] = { -#include "commands.lst" -}; diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..bc0e340 --- /dev/null +++ b/commands.h @@ -0,0 +1,83 @@ +#ifndef COMMANDS_H +#define COMMANDS_H +#include + +/* global */ +bool cg_change_gamma(); +bool cg_first(); +bool cg_mark_range(); +bool cg_n_or_last(); +bool cg_navigate_marked(); +bool cg_prefix_external(); +bool cg_quit(); +bool cg_reload_image(); +bool cg_remove_image(); +bool cg_reverse_marks(); +bool cg_scroll_screen(); +bool cg_switch_mode(); +bool cg_toggle_bar(); +bool cg_toggle_fullscreen(); +bool cg_toggle_image_mark(); +bool cg_unmark_all(); +bool cg_zoom(); +/* image mode */ +bool ci_alternate(); +bool ci_cursor_navigate(); +bool ci_drag(); +bool ci_fit_to_win(); +bool ci_flip(); +bool ci_navigate(); +bool ci_navigate_frame(); +bool ci_rotate(); +bool ci_scroll(); +bool ci_scroll_to_edge(); +bool ci_set_zoom(); +bool ci_slideshow(); +bool ci_toggle_alpha(); +bool ci_toggle_animation(); +bool ci_toggle_antialias(); +/* thumbnails mode */ +bool ct_move_sel(); +bool ct_reload_all(); + +/* global */ +#define g_change_gamma { cg_change_gamma, MODE_ALL } +#define g_first { cg_first, MODE_ALL } +#define g_mark_range { cg_mark_range, MODE_ALL } +#define g_n_or_last { cg_n_or_last, MODE_ALL } +#define g_navigate_marked { cg_navigate_marked, MODE_ALL } +#define g_prefix_external { cg_prefix_external, MODE_ALL } +#define g_quit { cg_quit, MODE_ALL } +#define g_reload_image { cg_reload_image, MODE_ALL } +#define g_remove_image { cg_remove_image, MODE_ALL } +#define g_reverse_marks { cg_reverse_marks, MODE_ALL } +#define g_scroll_screen { cg_scroll_screen, MODE_ALL } +#define g_switch_mode { cg_switch_mode, MODE_ALL } +#define g_toggle_bar { cg_toggle_bar, MODE_ALL } +#define g_toggle_fullscreen { cg_toggle_fullscreen, MODE_ALL } +#define g_toggle_image_mark { cg_toggle_image_mark, MODE_ALL } +#define g_unmark_all { cg_unmark_all, MODE_ALL } +#define g_zoom { cg_zoom, MODE_ALL } + +/* image mode */ +#define i_alternate { ci_alternate, MODE_IMAGE } +#define i_cursor_navigate { ci_cursor_navigate, MODE_IMAGE } +#define i_drag { ci_drag, MODE_IMAGE } +#define i_fit_to_win { ci_fit_to_win, MODE_IMAGE } +#define i_flip { ci_flip, MODE_IMAGE } +#define i_navigate { ci_navigate, MODE_IMAGE } +#define i_navigate_frame { ci_navigate_frame, MODE_IMAGE } +#define i_rotate { ci_rotate, MODE_IMAGE } +#define i_scroll { ci_scroll, MODE_IMAGE } +#define i_scroll_to_edge { ci_scroll_to_edge, MODE_IMAGE } +#define i_set_zoom { ci_set_zoom, MODE_IMAGE } +#define i_slideshow { ci_slideshow, MODE_IMAGE } +#define i_toggle_alpha { ci_toggle_alpha, MODE_IMAGE } +#define i_toggle_animation { ci_toggle_animation, MODE_IMAGE } +#define i_toggle_antialias { ci_toggle_antialias, MODE_IMAGE } + +/* thumbnails mode */ +#define t_move_sel { ct_move_sel, MODE_THUMB } +#define t_reload_all { ct_reload_all, MODE_THUMB } + +#endif diff --git a/commands.lst b/commands.lst deleted file mode 100644 index a97ca1c..0000000 --- a/commands.lst +++ /dev/null @@ -1,36 +0,0 @@ -G_CMD(quit) -G_CMD(switch_mode) -G_CMD(toggle_fullscreen) -G_CMD(toggle_bar) -G_CMD(prefix_external) -G_CMD(reload_image) -G_CMD(remove_image) -G_CMD(first) -G_CMD(n_or_last) -G_CMD(scroll_screen) -G_CMD(zoom) -G_CMD(toggle_image_mark) -G_CMD(reverse_marks) -G_CMD(mark_range) -G_CMD(unmark_all) -G_CMD(navigate_marked) -G_CMD(change_gamma) - -I_CMD(navigate) -I_CMD(cursor_navigate) -I_CMD(alternate) -I_CMD(navigate_frame) -I_CMD(toggle_animation) -I_CMD(scroll) -I_CMD(scroll_to_edge) -I_CMD(drag) -I_CMD(set_zoom) -I_CMD(fit_to_win) -I_CMD(rotate) -I_CMD(flip) -I_CMD(toggle_antialias) -I_CMD(toggle_alpha) -I_CMD(slideshow) - -T_CMD(move_sel) -T_CMD(reload_all) diff --git a/main.c b/main.c index a17e615..ffba285 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ */ #include "nsxiv.h" +#include "commands.h" #define _MAPPINGS_CONFIG #include "config.h" @@ -613,10 +614,10 @@ void on_keypress(XKeyEvent *kev) } else for (i = 0; i < ARRLEN(keys); i++) { if (keys[i].ksym == ksym && MODMASK(keys[i].mask | sh) == MODMASK(kev->state) && - keys[i].cmd >= 0 && keys[i].cmd < CMD_COUNT && - (cmds[keys[i].cmd].mode < 0 || cmds[keys[i].cmd].mode == mode)) + keys[i].cmd.func && + (keys[i].cmd.mode == MODE_ALL || keys[i].cmd.mode == mode)) { - if (cmds[keys[i].cmd].func(keys[i].arg)) + if (keys[i].cmd.func(keys[i].arg)) dirty = true; } } @@ -638,10 +639,10 @@ void on_buttonpress(XButtonEvent *bev) for (i = 0; i < ARRLEN(buttons); i++) { if (buttons[i].button == bev->button && MODMASK(buttons[i].mask) == MODMASK(bev->state) && - buttons[i].cmd >= 0 && buttons[i].cmd < CMD_COUNT && - (cmds[buttons[i].cmd].mode < 0 || cmds[buttons[i].cmd].mode == mode)) + buttons[i].cmd.func && + (buttons[i].cmd.mode == MODE_ALL || buttons[i].cmd.mode == mode)) { - if (cmds[buttons[i].cmd].func(buttons[i].arg)) + if (buttons[i].cmd.func(buttons[i].arg)) dirty = true; } } @@ -778,7 +779,7 @@ void run(void) break; case ClientMessage: if ((Atom) ev.xclient.data.l[0] == atoms[ATOM_WM_DELETE_WINDOW]) - cmds[g_quit].func(0); + cg_quit(); break; case DestroyNotify: exit(EXIT_FAILURE); diff --git a/nsxiv.h b/nsxiv.h index d65875b..45d1772 100644 --- a/nsxiv.h +++ b/nsxiv.h @@ -60,6 +60,7 @@ typedef enum { } byteorder_t; typedef enum { + MODE_ALL, MODE_IMAGE, MODE_THUMB } appmode_t; @@ -162,36 +163,25 @@ bool arl_handle(arl_t*); typedef int arg_t; typedef bool (*cmd_f)(arg_t); -#define G_CMD(c) g_##c, -#define I_CMD(c) i_##c, -#define T_CMD(c) t_##c, - -typedef enum { -#include "commands.lst" - CMD_COUNT -} cmd_id_t; - typedef struct { - int mode; cmd_f func; + appmode_t mode; } cmd_t; typedef struct { unsigned int mask; KeySym ksym; - cmd_id_t cmd; + cmd_t cmd; arg_t arg; } keymap_t; typedef struct { unsigned int mask; unsigned int button; - cmd_id_t cmd; + cmd_t cmd; arg_t arg; } button_t; -extern const cmd_t cmds[CMD_COUNT]; - /* image.c */