| @@ -23,6 +23,8 @@ |
| 23 | 23 | | #include <sys/select.h> |
| 24 | 24 | | #include <sys/stat.h> |
| 25 | 25 | | #include <sys/time.h> |
| 26 | + | #include <sys/wait.h> |
| 27 | + | #include <unistd.h> |
| 26 | 28 | | |
| 27 | 29 | | #include <X11/Xlib.h> |
| 28 | 30 | | #include <X11/Xutil.h> |
| @@ -33,6 +35,7 @@ |
| 33 | 35 | | #include "thumbs.h" |
| 34 | 36 | | #include "util.h" |
| 35 | 37 | | #include "window.h" |
| 38 | + | #include "commands.h" |
| 36 | 39 | | |
| 37 | 40 | | typedef enum { |
| 38 | 41 | | MODE_NORMAL = 0, |
| @@ -62,7 +65,7 @@ void cleanup() { |
| 62 | 65 | | static int in = 0; |
| 63 | 66 | | |
| 64 | 67 | | if (!in++) { |
| 65 | | − | img_close(&img); |
| 68 | + | img_close(&img, 0); |
| 66 | 69 | | img_free(&img); |
| 67 | 70 | | tns_free(&tns, &win); |
| 68 | 71 | | win_close(&win); |
| @@ -73,7 +76,7 @@ int load_image(int new) { |
| 73 | 76 | | struct stat fstats; |
| 74 | 77 | | |
| 75 | 78 | | if (new >= 0 && new < filecnt) { |
| 76 | | − | img_close(&img); |
| 79 | + | img_close(&img, 0); |
| 77 | 80 | | fileidx = new; |
| 78 | 81 | | if (!stat(filenames[fileidx], &fstats)) |
| 79 | 82 | | filesize = fstats.st_size; |
| @@ -270,6 +273,60 @@ void read_dir_rec(const char *dirname) { |
| 270 | 273 | | free(dirnames); |
| 271 | 274 | | } |
| 272 | 275 | | |
| 276 | + | int run_command(const char **cmdline, Bool reload) { |
| 277 | + | int argc, i; |
| 278 | + | const char **argv; |
| 279 | + | pid_t pid; |
| 280 | + | int error, ret, status; |
| 281 | + | |
| 282 | + | if (!cmdline) |
| 283 | + | return 0; |
| 284 | + | |
| 285 | + | argc = 1; |
| 286 | + | while (cmdline[argc-1]) |
| 287 | + | ++argc; |
| 288 | + | |
| 289 | + | if (argc < 2) |
| 290 | + | return 0; |
| 291 | + | |
| 292 | + | argv = (const char**) s_malloc(argc * sizeof(const char*)); |
| 293 | + | error = ret = 0; |
| 294 | + | |
| 295 | + | for (i = 0; i < argc; ++i) { |
| 296 | + | if (cmdline[i] != FILENAME) |
| 297 | + | argv[i] = cmdline[i]; |
| 298 | + | else |
| 299 | + | argv[i] = filenames[mode == MODE_NORMAL ? fileidx : tns.sel]; |
| 300 | + | } |
| 301 | + | |
| 302 | + | if ((pid = fork()) == 0) { |
| 303 | + | execvp(argv[0], (char **const) argv); |
| 304 | + | warn("could not exec %s", argv[0]); |
| 305 | + | exit(1); |
| 306 | + | } else if (pid < 0 && !options->quiet) { |
| 307 | + | warn("could not fork. command line was:"); |
| 308 | + | error = 1; |
| 309 | + | } else if (reload) { |
| 310 | + | waitpid(pid, &status, 0); |
| 311 | + | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
| 312 | + | ret = 1; |
| 313 | + | } else if (!options->quiet) { |
| 314 | + | warn("child exited with non-zero return value: %d. command line was:", |
| 315 | + | WEXITSTATUS(status)); |
| 316 | + | error = 1; |
| 317 | + | } |
| 318 | + | } |
| 319 | + | |
| 320 | + | if (error) { |
| 321 | + | for (i = 0; i < argc && argv[i]; ++i) |
| 322 | + | fprintf(stderr, "%s%s", i > 0 ? " " : "", argv[i]); |
| 323 | + | fprintf(stderr, "\n"); |
| 324 | + | } |
| 325 | + | |
| 326 | + | free(argv); |
| 327 | + | return ret; |
| 328 | + | } |
| 329 | + | |
| 273 | 330 | | |
| 274 | 331 | | /* event handling */ |
| 275 | 332 | | |
| @@ -293,7 +350,7 @@ void redraw() { |
| 293 | 350 | | } |
| 294 | 351 | | |
| 295 | 352 | | void on_keypress(XKeyEvent *kev) { |
| 296 | | − | int x, y; |
| 353 | + | int i, x, y; |
| 297 | 354 | | unsigned int w, h; |
| 298 | 355 | | char key; |
| 299 | 356 | | KeySym ksym; |
| @@ -305,6 +362,25 @@ void on_keypress(XKeyEvent *kev) { |
| 305 | 362 | | XLookupString(kev, &key, 1, &ksym, NULL); |
| 306 | 363 | | changed = 0; |
| 307 | 364 | | |
| 365 | + | /* external commands from commands.h */ |
| 366 | + | for (i = 0; i < LEN(commands); ++i) { |
| 367 | + | if (commands[i].ksym == ksym) { |
| 368 | + | win_set_cursor(&win, CURSOR_WATCH); |
| 369 | + | if (run_command(commands[i].cmdline, commands[i].reload)) { |
| 370 | + | if (mode == MODE_NORMAL) { |
| 371 | + | img_close(&img, 1); |
| 372 | + | load_image(fileidx); |
| 373 | + | tns_load(&tns, &win, fileidx, filenames[fileidx]); |
| 374 | + | } else { |
| 375 | + | tns_load(&tns, &win, tns.sel, filenames[tns.sel]); |
| 376 | + | } |
| 377 | + | redraw(); |
| 378 | + | } |
| 379 | + | win_set_cursor(&win, mode == MODE_NORMAL ? CURSOR_NONE : CURSOR_ARROW); |
| 380 | + | return; |
| 381 | + | } |
| 382 | + | } |
| 383 | + | |
| 308 | 384 | | if (mode == MODE_NORMAL) { |
| 309 | 385 | | switch (ksym) { |
| 310 | 386 | | /* navigate image list */ |
| @@ -395,7 +471,7 @@ void on_keypress(XKeyEvent *kev) { |
| 395 | 471 | | case XK_Return: |
| 396 | 472 | | if (!tns.thumbs) |
| 397 | 473 | | tns_init(&tns, filecnt); |
| 398 | | − | img_close(&img); |
| 474 | + | img_close(&img, 0); |
| 399 | 475 | | mode = MODE_THUMBS; |
| 400 | 476 | | win_set_cursor(&win, CURSOR_ARROW); |
| 401 | 477 | | timo_cursor = 0; |