diff options
-rw-r--r-- | commands.h | 24 | ||||
-rw-r--r-- | image.c | 7 | ||||
-rw-r--r-- | image.h | 2 | ||||
-rw-r--r-- | main.c | 84 | ||||
-rw-r--r-- | thumbs.c | 8 | ||||
-rw-r--r-- | window.c | 2 |
6 files changed, 115 insertions, 12 deletions
diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..6fcd602 --- /dev/null +++ b/commands.h @@ -0,0 +1,24 @@ +#define FILENAME (const char*) 0x1 + +typedef struct { + KeySym ksym; + const char **cmdline; + Bool reload; +} command_t; + +static const char *cmdline_1[] = { "jpegtran", "-rotate", "270", "-copy", "all", + "-outfile", FILENAME, FILENAME, NULL }; +static const char *cmdline_2[] = { "jpegtran", "-rotate", "90", "-copy", "all", + "-outfile", FILENAME, FILENAME, NULL }; +static const char *cmdline_3[] = { "mogrify", "-rotate", "-90", FILENAME, + NULL }; +static const char *cmdline_4[] = { "mogrify", "-rotate", "+90", FILENAME, + NULL }; + +static command_t commands[] = { + /* key command-line reload? */ + { XK_a, cmdline_1, True }, + { XK_s, cmdline_2, True }, + { XK_A, cmdline_3, True }, + { XK_S, cmdline_4, True }, +}; @@ -99,10 +99,13 @@ int img_load(img_t *img, const char *filename) { return 1; } -void img_close(img_t *img) { +void img_close(img_t *img, int decache) { if (img && img->im) { imlib_context_set_image(img->im); - imlib_free_image(); + if (decache) + imlib_free_image_and_decache(); + else + imlib_free_image(); img->im = NULL; } } @@ -57,7 +57,7 @@ void img_free(img_t*); int img_check(const char*); int img_load(img_t*, const char*); -void img_close(img_t*); +void img_close(img_t*, int); void img_render(img_t*, win_t*); @@ -23,6 +23,8 @@ #include <sys/select.h> #include <sys/stat.h> #include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -33,6 +35,7 @@ #include "thumbs.h" #include "util.h" #include "window.h" +#include "commands.h" typedef enum { MODE_NORMAL = 0, @@ -62,7 +65,7 @@ void cleanup() { static int in = 0; if (!in++) { - img_close(&img); + img_close(&img, 0); img_free(&img); tns_free(&tns, &win); win_close(&win); @@ -73,7 +76,7 @@ int load_image(int new) { struct stat fstats; if (new >= 0 && new < filecnt) { - img_close(&img); + img_close(&img, 0); fileidx = new; if (!stat(filenames[fileidx], &fstats)) filesize = fstats.st_size; @@ -270,6 +273,60 @@ void read_dir_rec(const char *dirname) { free(dirnames); } +int run_command(const char **cmdline, Bool reload) { + int argc, i; + const char **argv; + pid_t pid; + int error, ret, status; + + if (!cmdline) + return 0; + + argc = 1; + while (cmdline[argc-1]) + ++argc; + + if (argc < 2) + return 0; + + argv = (const char**) s_malloc(argc * sizeof(const char*)); + error = ret = 0; + + for (i = 0; i < argc; ++i) { + if (cmdline[i] != FILENAME) + argv[i] = cmdline[i]; + else + argv[i] = filenames[mode == MODE_NORMAL ? fileidx : tns.sel]; + } + + if ((pid = fork()) == 0) { + execvp(argv[0], (char **const) argv); + warn("could not exec %s", argv[0]); + exit(1); + } else if (pid < 0 && !options->quiet) { + warn("could not fork. command line was:"); + error = 1; + } else if (reload) { + waitpid(pid, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + ret = 1; + } else if (!options->quiet) { + warn("child exited with non-zero return value: %d. command line was:", + WEXITSTATUS(status)); + error = 1; + } + } + + if (error) { + for (i = 0; i < argc && argv[i]; ++i) + fprintf(stderr, "%s%s", i > 0 ? " " : "", argv[i]); + fprintf(stderr, "\n"); + } + + free(argv); + return ret; +} + /* event handling */ @@ -293,7 +350,7 @@ void redraw() { } void on_keypress(XKeyEvent *kev) { - int x, y; + int i, x, y; unsigned int w, h; char key; KeySym ksym; @@ -305,6 +362,25 @@ void on_keypress(XKeyEvent *kev) { XLookupString(kev, &key, 1, &ksym, NULL); changed = 0; + /* external commands from commands.h */ + for (i = 0; i < LEN(commands); ++i) { + if (commands[i].ksym == ksym) { + win_set_cursor(&win, CURSOR_WATCH); + if (run_command(commands[i].cmdline, commands[i].reload)) { + if (mode == MODE_NORMAL) { + img_close(&img, 1); + load_image(fileidx); + tns_load(&tns, &win, fileidx, filenames[fileidx]); + } else { + tns_load(&tns, &win, tns.sel, filenames[tns.sel]); + } + redraw(); + } + win_set_cursor(&win, mode == MODE_NORMAL ? CURSOR_NONE : CURSOR_ARROW); + return; + } + } + if (mode == MODE_NORMAL) { switch (ksym) { /* navigate image list */ @@ -395,7 +471,7 @@ void on_keypress(XKeyEvent *kev) { case XK_Return: if (!tns.thumbs) tns_init(&tns, filecnt); - img_close(&img); + img_close(&img, 0); mode = MODE_THUMBS; win_set_cursor(&win, CURSOR_ARROW); timo_cursor = 0; @@ -66,12 +66,10 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { else if (n >= tns->cnt) tns->cnt = n + 1; - if ((im = imlib_load_image(filename))) { + if ((im = imlib_load_image(filename))) imlib_context_set_image(im); - imlib_image_set_changes_on_disk(); - } else { + else imlib_context_set_image(im_broken); - } w = imlib_image_get_width(); h = imlib_image_get_height(); @@ -95,7 +93,7 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { tns->dirty = 1; if (im) - imlib_free_image(); + imlib_free_image_and_decache(); } void tns_check_view(tns_t *tns, Bool scrolled) { @@ -331,4 +331,6 @@ void win_set_cursor(win_t *win, win_cur_t cursor) { XDefineCursor(win->env.dpy, win->xwin, carrow); break; } + + XFlush(win->env.dpy); } |