nsxivf2e0c49
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.
+98 −100
7 files changed
- M Makefile +2 −2
- M commands.c +0 −66
- M commands.h +0 −2
- M config.def.h +0 −17
- R image-info → exec/image-info +0 −0
- A exec/key-handler +19 −0
- M main.c +77 −13
| @@ -35,8 +35,8 @@ install: all | |||
| 35 | 35 | sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | |
| 36 | 36 | chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | |
| 37 | 37 | mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec | |
| 38 | − | cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info | |
| 39 | − | chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info | |
| 38 | + | cp exec/* $(DESTDIR)$(PREFIX)/share/sxiv/exec/ | |
| 39 | + | chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/* | |
| 40 | 40 | ||
| 41 | 41 | uninstall: | |
| 42 | 42 | rm -f $(DESTDIR)$(PREFIX)/bin/sxiv | |
| @@ -504,69 +504,3 @@ bool it_toggle_alpha(arg_t a) | |||
| 504 | 504 | return true; | |
| 505 | 505 | } | |
| 506 | 506 | ||
| 507 | − | bool it_open_with(arg_t a) | |
| 508 | − | { | |
| 509 | − | const char *prog = (const char*) a; | |
| 510 | − | pid_t pid; | |
| 511 | − | ||
| 512 | − | if (prog == NULL || *prog == '\0') | |
| 513 | − | return false; | |
| 514 | − | ||
| 515 | − | if ((pid = fork()) == 0) { | |
| 516 | − | execlp(prog, prog, | |
| 517 | − | files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL); | |
| 518 | − | warn("could not exec: %s", prog); | |
| 519 | − | exit(EXIT_FAILURE); | |
| 520 | − | } else if (pid < 0) { | |
| 521 | − | warn("could not fork. program was: %s", prog); | |
| 522 | − | } | |
| 523 | − | return false; | |
| 524 | − | } | |
| 525 | − | ||
| 526 | − | bool it_shell_cmd(arg_t a) | |
| 527 | − | { | |
| 528 | − | int n, status; | |
| 529 | − | const char *cmdline = (const char*) a; | |
| 530 | − | pid_t pid; | |
| 531 | − | ||
| 532 | − | if (cmdline == NULL || *cmdline == '\0') | |
| 533 | − | return false; | |
| 534 | − | ||
| 535 | − | n = mode == MODE_IMAGE ? fileidx : tns.sel; | |
| 536 | − | ||
| 537 | − | if (setenv("SXIV_IMG", files[n].path, 1) < 0) { | |
| 538 | − | warn("could not set env.-variable: SXIV_IMG. command line was: %s", | |
| 539 | − | cmdline); | |
| 540 | − | return false; | |
| 541 | − | } | |
| 542 | − | ||
| 543 | − | if ((pid = fork()) == 0) { | |
| 544 | − | execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL); | |
| 545 | − | warn("could not exec: /bin/sh. command line was: %s", cmdline); | |
| 546 | − | exit(EXIT_FAILURE); | |
| 547 | − | } else if (pid < 0) { | |
| 548 | − | warn("could not fork. command line was: %s", cmdline); | |
| 549 | − | return false; | |
| 550 | − | } | |
| 551 | − | ||
| 552 | − | win_set_cursor(&win, CURSOR_WATCH); | |
| 553 | − | ||
| 554 | − | waitpid(pid, &status, 0); | |
| 555 | − | if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) | |
| 556 | − | warn("child exited with non-zero return value: %d. command line was: %s", | |
| 557 | − | WEXITSTATUS(status), cmdline); | |
| 558 | − | ||
| 559 | − | if (mode == MODE_IMAGE) { | |
| 560 | − | img_close(&img, true); | |
| 561 | − | load_image(fileidx); | |
| 562 | − | } | |
| 563 | − | if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) && | |
| 564 | − | mode == MODE_THUMB) | |
| 565 | − | { | |
| 566 | − | remove_file(tns.sel, false); | |
| 567 | − | tns.dirty = true; | |
| 568 | − | if (tns.sel >= tns.cnt) | |
| 569 | − | tns.sel = tns.cnt - 1; | |
| 570 | − | } | |
| 571 | − | return true; | |
| 572 | − | } | |
| @@ -69,7 +69,5 @@ bool i_flip(arg_t); | |||
| 69 | 69 | bool i_toggle_antialias(arg_t); | |
| 70 | 70 | bool i_change_gamma(arg_t); | |
| 71 | 71 | bool it_toggle_alpha(arg_t); | |
| 72 | − | bool it_open_with(arg_t); | |
| 73 | − | bool it_shell_cmd(arg_t); | |
| 74 | 72 | ||
| 75 | 73 | #endif /* COMMANDS_H */ | |
| @@ -151,23 +151,6 @@ static const keymap_t keys[] = { | |||
| 151 | 151 | { 0, XK_braceleft, i_change_gamma, (arg_t) -1 }, | |
| 152 | 152 | { 0, XK_braceright, i_change_gamma, (arg_t) +1 }, | |
| 153 | 153 | { ControlMask, XK_G, i_change_gamma, (arg_t) 0 }, | |
| 154 | − | ||
| 155 | − | /* open current image with given program: */ | |
| 156 | − | { ControlMask, XK_g, it_open_with, (arg_t) "gimp" }, | |
| 157 | − | ||
| 158 | − | /* run shell command line on current file ("$SXIV_IMG"): */ | |
| 159 | − | { ControlMask, XK_less, it_shell_cmd, (arg_t) \ | |
| 160 | − | "mogrify -rotate -90 \"$SXIV_IMG\"" }, | |
| 161 | − | { ControlMask, XK_greater, it_shell_cmd, (arg_t) \ | |
| 162 | − | "mogrify -rotate +90 \"$SXIV_IMG\"" }, | |
| 163 | − | { ControlMask, XK_question, it_shell_cmd, (arg_t) \ | |
| 164 | − | "mogrify -rotate 180 \"$SXIV_IMG\"" }, | |
| 165 | − | { ControlMask, XK_comma, it_shell_cmd, (arg_t) \ | |
| 166 | − | "jpegtran -rotate 270 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, | |
| 167 | − | { ControlMask, XK_period, it_shell_cmd, (arg_t) \ | |
| 168 | − | "jpegtran -rotate 90 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, | |
| 169 | − | { ControlMask, XK_slash, it_shell_cmd, (arg_t) \ | |
| 170 | − | "jpegtran -rotate 180 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" }, | |
| 171 | 154 | }; | |
| 172 | 155 | ||
| 173 | 156 | /* mouse button mappings for image mode: */ | |
[No content changes]
| @@ -0,0 +1,19 @@ | |||
| 1 | + | #!/bin/sh | |
| 2 | + | ||
| 3 | + | case "$1" in | |
| 4 | + | "C-g") | |
| 5 | + | gimp "$2" & ;; | |
| 6 | + | "C-comma") | |
| 7 | + | exec jpegtran -rotate 270 -copy all -outfile "$2" "$2" ;; | |
| 8 | + | "C-period") | |
| 9 | + | exec jpegtran -rotate 90 -copy all -outfile "$2" "$2" ;; | |
| 10 | + | "C-slash") | |
| 11 | + | exec jpegtran -rotate 180 -copy all -outfile "$2" "$2" ;; | |
| 12 | + | "C-less") | |
| 13 | + | exec mogrify -rotate -90 "$2" ;; | |
| 14 | + | "C-greater") | |
| 15 | + | exec mogrify -rotate +90 "$2" ;; | |
| 16 | + | "C-question") | |
| 17 | + | exec mogrify -rotate 180 "$2" ;; | |
| 18 | + | esac | |
| 19 | + | ||
| @@ -46,6 +46,18 @@ enum { | |||
| 46 | 46 | TITLE_LEN = 256 | |
| 47 | 47 | }; | |
| 48 | 48 | ||
| 49 | + | #define EXEC_REL_DIR ".sxiv/exec" | |
| 50 | + | ||
| 51 | + | enum { | |
| 52 | + | EXEC_INFO, | |
| 53 | + | EXEC_KEY | |
| 54 | + | }; | |
| 55 | + | ||
| 56 | + | typedef struct { | |
| 57 | + | const char *name; | |
| 58 | + | char *cmd; | |
| 59 | + | } exec_t; | |
| 60 | + | ||
| 49 | 61 | typedef struct { | |
| 50 | 62 | struct timeval when; | |
| 51 | 63 | bool active; | |
| @@ -71,9 +83,13 @@ int prefix; | |||
| 71 | 83 | ||
| 72 | 84 | bool resized = false; | |
| 73 | 85 | ||
| 74 | − | const char * const INFO_SCRIPT = ".sxiv/exec/image-info"; | |
| 86 | + | exec_t exec[] = { | |
| 87 | + | { "image-info", NULL }, | |
| 88 | + | { "key-handler", NULL } | |
| 89 | + | }; | |
| 90 | + | ||
| 75 | 91 | struct { | |
| 76 | − | char *script; | |
| 92 | + | char *cmd; | |
| 77 | 93 | int fd; | |
| 78 | 94 | unsigned int i, lastsep; | |
| 79 | 95 | bool open; | |
| @@ -221,7 +237,7 @@ void open_info(void) | |||
| 221 | 237 | static pid_t pid; | |
| 222 | 238 | int pfd[2]; | |
| 223 | 239 | ||
| 224 | − | if (info.script == NULL || info.open || win.bar.h == 0) | |
| 240 | + | if (info.cmd == NULL || info.open || win.bar.h == 0) | |
| 225 | 241 | return; | |
| 226 | 242 | if (info.fd != -1) { | |
| 227 | 243 | close(info.fd); | |
| @@ -242,8 +258,8 @@ void open_info(void) | |||
| 242 | 258 | } else if (pid == 0) { | |
| 243 | 259 | close(pfd[0]); | |
| 244 | 260 | dup2(pfd[1], 1); | |
| 245 | − | execl(info.script, info.script, files[fileidx].name, NULL); | |
| 246 | − | warn("could not exec: %s", info.script); | |
| 261 | + | execl(info.cmd, info.cmd, files[fileidx].name, NULL); | |
| 262 | + | warn("could not exec: %s", info.cmd); | |
| 247 | 263 | exit(EXIT_FAILURE); | |
| 248 | 264 | } | |
| 249 | 265 | } | |
| @@ -356,7 +372,7 @@ void update_info(void) | |||
| 356 | 372 | fn, img.multi.sel + 1, img.multi.cnt); | |
| 357 | 373 | } | |
| 358 | 374 | n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt); | |
| 359 | − | ow_info = info.script == NULL; | |
| 375 | + | ow_info = info.cmd == NULL; | |
| 360 | 376 | } | |
| 361 | 377 | if (ow_info) { | |
| 362 | 378 | fn = strlen(files[sel].name); | |
| @@ -418,6 +434,49 @@ void clear_resize(void) | |||
| 418 | 434 | resized = false; | |
| 419 | 435 | } | |
| 420 | 436 | ||
| 437 | + | void key_handler(const char *key, unsigned int mask) | |
| 438 | + | { | |
| 439 | + | pid_t pid; | |
| 440 | + | int retval, status, n = mode == MODE_IMAGE ? fileidx : tns.sel; | |
| 441 | + | char *cmd = exec[EXEC_KEY].cmd, kstr[32]; | |
| 442 | + | ||
| 443 | + | if (cmd == NULL || key == NULL) | |
| 444 | + | return; | |
| 445 | + | ||
| 446 | + | snprintf(kstr, sizeof(kstr), "%s%s%s%s", | |
| 447 | + | mask & ControlMask ? "C-" : "", | |
| 448 | + | mask & Mod1Mask ? "M-" : "", | |
| 449 | + | mask & ShiftMask ? "S-" : "", key); | |
| 450 | + | ||
| 451 | + | if ((pid = fork()) == 0) { | |
| 452 | + | execl(cmd, cmd, kstr, files[n].path, NULL); | |
| 453 | + | warn("could not exec key handler"); | |
| 454 | + | exit(EXIT_FAILURE); | |
| 455 | + | } else if (pid < 0) { | |
| 456 | + | warn("could not fork key handler"); | |
| 457 | + | return; | |
| 458 | + | } | |
| 459 | + | win_set_cursor(&win, CURSOR_WATCH); | |
| 460 | + | ||
| 461 | + | waitpid(pid, &status, 0); | |
| 462 | + | retval = WEXITSTATUS(status); | |
| 463 | + | if (WIFEXITED(status) == 0 || retval != 0) | |
| 464 | + | warn("key handler exited with non-zero return value: %d", retval); | |
| 465 | + | if (mode == MODE_IMAGE) { | |
| 466 | + | img_close(&img, true); | |
| 467 | + | load_image(fileidx); | |
| 468 | + | } | |
| 469 | + | if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) && | |
| 470 | + | mode == MODE_THUMB) | |
| 471 | + | { | |
| 472 | + | remove_file(tns.sel, false); | |
| 473 | + | tns.dirty = true; | |
| 474 | + | if (tns.sel >= tns.cnt) | |
| 475 | + | tns.sel = tns.cnt - 1; | |
| 476 | + | } | |
| 477 | + | redraw(); | |
| 478 | + | } | |
| 479 | + | ||
| 421 | 480 | #define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask)) | |
| 422 | 481 | ||
| 423 | 482 | void on_keypress(XKeyEvent *kev) | |
| @@ -438,6 +497,9 @@ void on_keypress(XKeyEvent *kev) | |||
| 438 | 497 | XLookupString(kev, &key, 1, &ksym, NULL); | |
| 439 | 498 | sh = (kev->state & ShiftMask) && ksym != shksym ? ShiftMask : 0; | |
| 440 | 499 | ||
| 500 | + | if (IsModifierKey(ksym)) | |
| 501 | + | return; | |
| 502 | + | ||
| 441 | 503 | if ((ksym == XK_Escape && MODMASK(kev->state) == 0) || | |
| 442 | 504 | (key >= '0' && key <= '9')) | |
| 443 | 505 | { | |
| @@ -456,6 +518,7 @@ void on_keypress(XKeyEvent *kev) | |||
| 456 | 518 | return; | |
| 457 | 519 | } | |
| 458 | 520 | } | |
| 521 | + | key_handler(XKeysymToString(ksym), kev->state & ~sh); | |
| 459 | 522 | } | |
| 460 | 523 | ||
| 461 | 524 | void on_buttonpress(XButtonEvent *bev) | |
| @@ -706,16 +769,17 @@ int main(int argc, char **argv) | |||
| 706 | 769 | ||
| 707 | 770 | if ((homedir = getenv("HOME")) == NULL) { | |
| 708 | 771 | warn("could not locate home directory"); | |
| 709 | − | } else { | |
| 710 | − | len = strlen(homedir) + strlen(INFO_SCRIPT) + 2; | |
| 711 | − | info.script = (char*) s_malloc(len); | |
| 712 | − | snprintf(info.script, len, "%s/%s", homedir, INFO_SCRIPT); | |
| 713 | − | if (access(info.script, X_OK) != 0) { | |
| 714 | − | free(info.script); | |
| 715 | − | info.script = NULL; | |
| 772 | + | } else for (i = 0; i < ARRLEN(exec); i++) { | |
| 773 | + | len = strlen(homedir) + strlen(EXEC_REL_DIR) + strlen(exec[i].name) + 3; | |
| 774 | + | exec[i].cmd = (char*) s_malloc(len); | |
| 775 | + | snprintf(exec[i].cmd, len, "%s/%s/%s", homedir, EXEC_REL_DIR, exec[i].name); | |
| 776 | + | if (access(exec[i].cmd, X_OK) != 0) { | |
| 777 | + | free(exec[i].cmd); | |
| 778 | + | exec[i].cmd = NULL; | |
| 716 | 779 | } | |
| 717 | 780 | } | |
| 718 | 781 | info.fd = -1; | |
| 782 | + | info.cmd = exec[EXEC_INFO].cmd; | |
| 719 | 783 | ||
| 720 | 784 | if (options->thumb_mode) { | |
| 721 | 785 | mode = MODE_THUMB; | |