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.
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								commands.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								config.def.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								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: */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								exec/key-handler
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								exec/key-handler
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										90
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user