From f2e0c492bd784a3a927550187e21cfbc6bbb0939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Thu, 2 Jan 2014 23:19:31 +0100 Subject: [PATCH] Moved external shell commands into exec/key-handler script Gets called on all unset key mappings. Arguments are: key combo and current file. Thanks to Francesco Orsenigo (xarvh) for the idea. --- Makefile | 4 +- commands.c | 66 ------------------------- commands.h | 2 - config.def.h | 17 ------- image-info => exec/image-info | 0 exec/key-handler | 19 ++++++++ main.c | 90 ++++++++++++++++++++++++++++++----- 7 files changed, 98 insertions(+), 100 deletions(-) rename image-info => exec/image-info (100%) create mode 100644 exec/key-handler diff --git a/Makefile b/Makefile index 17dccb4..cf611c3 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,8 @@ install: all sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec - cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info - chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info + cp exec/* $(DESTDIR)$(PREFIX)/share/sxiv/exec/ + chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/* uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/sxiv diff --git a/commands.c b/commands.c index 49298bf..9c3d7bf 100644 --- a/commands.c +++ b/commands.c @@ -504,69 +504,3 @@ bool it_toggle_alpha(arg_t a) return true; } -bool it_open_with(arg_t a) -{ - const char *prog = (const char*) a; - pid_t pid; - - if (prog == NULL || *prog == '\0') - return false; - - if ((pid = fork()) == 0) { - execlp(prog, prog, - files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL); - warn("could not exec: %s", prog); - exit(EXIT_FAILURE); - } else if (pid < 0) { - warn("could not fork. program was: %s", prog); - } - return false; -} - -bool it_shell_cmd(arg_t a) -{ - int n, status; - const char *cmdline = (const char*) a; - pid_t pid; - - if (cmdline == NULL || *cmdline == '\0') - return false; - - n = mode == MODE_IMAGE ? fileidx : tns.sel; - - if (setenv("SXIV_IMG", files[n].path, 1) < 0) { - warn("could not set env.-variable: SXIV_IMG. command line was: %s", - cmdline); - return false; - } - - if ((pid = fork()) == 0) { - execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL); - warn("could not exec: /bin/sh. command line was: %s", cmdline); - exit(EXIT_FAILURE); - } else if (pid < 0) { - warn("could not fork. command line was: %s", cmdline); - return false; - } - - win_set_cursor(&win, CURSOR_WATCH); - - waitpid(pid, &status, 0); - if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) - warn("child exited with non-zero return value: %d. command line was: %s", - WEXITSTATUS(status), cmdline); - - if (mode == MODE_IMAGE) { - img_close(&img, true); - load_image(fileidx); - } - if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) && - mode == MODE_THUMB) - { - remove_file(tns.sel, false); - tns.dirty = true; - if (tns.sel >= tns.cnt) - tns.sel = tns.cnt - 1; - } - return true; -} diff --git a/commands.h b/commands.h index 65c84e7..1002d92 100644 --- a/commands.h +++ b/commands.h @@ -69,7 +69,5 @@ bool i_flip(arg_t); bool i_toggle_antialias(arg_t); bool i_change_gamma(arg_t); bool it_toggle_alpha(arg_t); -bool it_open_with(arg_t); -bool it_shell_cmd(arg_t); #endif /* COMMANDS_H */ diff --git a/config.def.h b/config.def.h index 6a0f1dc..86ba0f5 100644 --- a/config.def.h +++ b/config.def.h @@ -151,23 +151,6 @@ static const keymap_t keys[] = { { 0, XK_braceleft, i_change_gamma, (arg_t) -1 }, { 0, XK_braceright, i_change_gamma, (arg_t) +1 }, { ControlMask, XK_G, i_change_gamma, (arg_t) 0 }, - - /* open current image with given program: */ - { ControlMask, XK_g, it_open_with, (arg_t) "gimp" }, - - /* run shell command line on current file ("$SXIV_IMG"): */ - { ControlMask, XK_less, it_shell_cmd, (arg_t) \ - "mogrify -rotate -90 \"$SXIV_IMG\"" }, - { ControlMask, XK_greater, it_shell_cmd, (arg_t) \ - "mogrify -rotate +90 \"$SXIV_IMG\"" }, - { ControlMask, XK_question, it_shell_cmd, (arg_t) \ - "mogrify -rotate 180 \"$SXIV_IMG\"" }, - { ControlMask, XK_comma, it_shell_cmd, (arg_t) \ - "jpegtran -rotate 270 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, - { ControlMask, XK_period, it_shell_cmd, (arg_t) \ - "jpegtran -rotate 90 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, - { ControlMask, XK_slash, it_shell_cmd, (arg_t) \ - "jpegtran -rotate 180 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, }; /* mouse button mappings for image mode: */ diff --git a/image-info b/exec/image-info similarity index 100% rename from image-info rename to exec/image-info diff --git a/exec/key-handler b/exec/key-handler new file mode 100644 index 0000000..d2e8aa2 --- /dev/null +++ b/exec/key-handler @@ -0,0 +1,19 @@ +#!/bin/sh + +case "$1" in +"C-g") + gimp "$2" & ;; +"C-comma") + exec jpegtran -rotate 270 -copy all -outfile "$2" "$2" ;; +"C-period") + exec jpegtran -rotate 90 -copy all -outfile "$2" "$2" ;; +"C-slash") + exec jpegtran -rotate 180 -copy all -outfile "$2" "$2" ;; +"C-less") + exec mogrify -rotate -90 "$2" ;; +"C-greater") + exec mogrify -rotate +90 "$2" ;; +"C-question") + exec mogrify -rotate 180 "$2" ;; +esac + diff --git a/main.c b/main.c index f89a064..5789ff0 100644 --- a/main.c +++ b/main.c @@ -46,6 +46,18 @@ enum { TITLE_LEN = 256 }; +#define EXEC_REL_DIR ".sxiv/exec" + +enum { + EXEC_INFO, + EXEC_KEY +}; + +typedef struct { + const char *name; + char *cmd; +} exec_t; + typedef struct { struct timeval when; bool active; @@ -71,9 +83,13 @@ int prefix; bool resized = false; -const char * const INFO_SCRIPT = ".sxiv/exec/image-info"; +exec_t exec[] = { + { "image-info", NULL }, + { "key-handler", NULL } +}; + struct { - char *script; + char *cmd; int fd; unsigned int i, lastsep; bool open; @@ -221,7 +237,7 @@ void open_info(void) static pid_t pid; int pfd[2]; - if (info.script == NULL || info.open || win.bar.h == 0) + if (info.cmd == NULL || info.open || win.bar.h == 0) return; if (info.fd != -1) { close(info.fd); @@ -242,8 +258,8 @@ void open_info(void) } else if (pid == 0) { close(pfd[0]); dup2(pfd[1], 1); - execl(info.script, info.script, files[fileidx].name, NULL); - warn("could not exec: %s", info.script); + execl(info.cmd, info.cmd, files[fileidx].name, NULL); + warn("could not exec: %s", info.cmd); exit(EXIT_FAILURE); } } @@ -356,7 +372,7 @@ void update_info(void) fn, img.multi.sel + 1, img.multi.cnt); } n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt); - ow_info = info.script == NULL; + ow_info = info.cmd == NULL; } if (ow_info) { fn = strlen(files[sel].name); @@ -418,6 +434,49 @@ void clear_resize(void) resized = false; } +void key_handler(const char *key, unsigned int mask) +{ + pid_t pid; + int retval, status, n = mode == MODE_IMAGE ? fileidx : tns.sel; + char *cmd = exec[EXEC_KEY].cmd, kstr[32]; + + if (cmd == NULL || key == NULL) + return; + + snprintf(kstr, sizeof(kstr), "%s%s%s%s", + mask & ControlMask ? "C-" : "", + mask & Mod1Mask ? "M-" : "", + mask & ShiftMask ? "S-" : "", key); + + if ((pid = fork()) == 0) { + execl(cmd, cmd, kstr, files[n].path, NULL); + warn("could not exec key handler"); + exit(EXIT_FAILURE); + } else if (pid < 0) { + warn("could not fork key handler"); + return; + } + win_set_cursor(&win, CURSOR_WATCH); + + waitpid(pid, &status, 0); + retval = WEXITSTATUS(status); + if (WIFEXITED(status) == 0 || retval != 0) + warn("key handler exited with non-zero return value: %d", retval); + if (mode == MODE_IMAGE) { + img_close(&img, true); + load_image(fileidx); + } + if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) && + mode == MODE_THUMB) + { + remove_file(tns.sel, false); + tns.dirty = true; + if (tns.sel >= tns.cnt) + tns.sel = tns.cnt - 1; + } + redraw(); +} + #define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask)) void on_keypress(XKeyEvent *kev) @@ -438,6 +497,9 @@ void on_keypress(XKeyEvent *kev) XLookupString(kev, &key, 1, &ksym, NULL); sh = (kev->state & ShiftMask) && ksym != shksym ? ShiftMask : 0; + if (IsModifierKey(ksym)) + return; + if ((ksym == XK_Escape && MODMASK(kev->state) == 0) || (key >= '0' && key <= '9')) { @@ -456,6 +518,7 @@ void on_keypress(XKeyEvent *kev) return; } } + key_handler(XKeysymToString(ksym), kev->state & ~sh); } void on_buttonpress(XButtonEvent *bev) @@ -706,16 +769,17 @@ int main(int argc, char **argv) if ((homedir = getenv("HOME")) == NULL) { warn("could not locate home directory"); - } else { - len = strlen(homedir) + strlen(INFO_SCRIPT) + 2; - info.script = (char*) s_malloc(len); - snprintf(info.script, len, "%s/%s", homedir, INFO_SCRIPT); - if (access(info.script, X_OK) != 0) { - free(info.script); - info.script = NULL; + } else for (i = 0; i < ARRLEN(exec); i++) { + len = strlen(homedir) + strlen(EXEC_REL_DIR) + strlen(exec[i].name) + 3; + exec[i].cmd = (char*) s_malloc(len); + snprintf(exec[i].cmd, len, "%s/%s/%s", homedir, EXEC_REL_DIR, exec[i].name); + if (access(exec[i].cmd, X_OK) != 0) { + free(exec[i].cmd); + exec[i].cmd = NULL; } } info.fd = -1; + info.cmd = exec[EXEC_INFO].cmd; if (options->thumb_mode) { mode = MODE_THUMB;