From c78cee50a4c33e2286ad7ffe9f28e0fc4ef3bd89 Mon Sep 17 00:00:00 2001
From: Yu-Jie Lin <livibetter@gmail.com>
Date: Tue, 9 Aug 2011 17:29:57 +0800
Subject: Add flip/mirror in-placec edit actions (derf/#9)

---
 src/feh.h       |  3 +++
 src/imlib.c     | 45 +++++++++++++++++++++++++++++++--------------
 src/keyevents.c | 14 ++++++++++++--
 src/menu.c      |  2 +-
 src/options.h   |  2 ++
 5 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/src/feh.h b/src/feh.h
index 63aeef6..811a5e3 100644
--- a/src/feh.h
+++ b/src/feh.h
@@ -98,6 +98,9 @@ enum slide_change { SLIDE_NEXT, SLIDE_PREV, SLIDE_RAND, SLIDE_FIRST, SLIDE_LAST,
 	SLIDE_JUMP_BACK
 };
 
+#define INPLACE_EDIT_FLIP   -1
+#define INPLACE_EDIT_MIRROR -2
+
 typedef void (*sighandler_t) (int);
 
 int feh_main_iteration(int block);
diff --git a/src/imlib.c b/src/imlib.c
index 2b6f200..f5e63c3 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -786,7 +786,7 @@ void feh_display_status(char stat)
 	return;
 }
 
-void feh_edit_inplace_orient(winwidget w, int orientation)
+void feh_edit_inplace(winwidget w, int op)
 {
 	int ret;
 	Imlib_Image old;
@@ -794,14 +794,21 @@ void feh_edit_inplace_orient(winwidget w, int orientation)
 		return;
 
 	if (!strcmp(gib_imlib_image_format(w->im), "jpeg")) {
-		feh_edit_inplace_lossless_rotate(w, orientation);
+		feh_edit_inplace_lossless(w, op);
 		feh_reload_image(w, 1, 1);
 		return;
 	}
 
 	ret = feh_load_image(&old, FEH_FILE(w->file->data));
 	if (ret) {
-		gib_imlib_image_orientate(old, orientation);
+		if (op == INPLACE_EDIT_FLIP) {
+			imlib_context_set_image(old);
+			imlib_image_flip_vertical();
+		} else if (op == INPLACE_EDIT_MIRROR) {
+			imlib_context_set_image(old);
+			imlib_image_flip_horizontal();
+		} else
+			gib_imlib_image_orientate(old, op);
 		gib_imlib_save_image(old, FEH_FILE(w->file->data)->filename);
 		gib_imlib_free_image(old);
 		feh_reload_image(w, 1, 1);
@@ -910,37 +917,47 @@ gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style *
 	return lines;
 }
 
-void feh_edit_inplace_lossless_rotate(winwidget w, int orientation)
+void feh_edit_inplace_lossless(winwidget w, int op)
 {
 	char *filename = FEH_FILE(w->file->data)->filename;
-	char rotate_str[4];
 	int len = strlen(filename) + 1;
 	char *file_str = emalloc(len);
-	int rotatearg = 90 * orientation;
 	int pid, status;
+	char op_name[]  = "rotate";     // for message
+	char op_op[]    = "-rotate";    // for jpegtran option
+	char op_value[] = "horizontal"; // for jpegtran option's value
+
+	if (op == INPLACE_EDIT_FLIP) {
+		sprintf(op_name,  "flip");
+		sprintf(op_op,    "-flip");
+		sprintf(op_value, "vertical");
+	} else if (op == INPLACE_EDIT_MIRROR) {
+		sprintf(op_name,  "mirror");
+		sprintf(op_op,    "-flip");
+	} else
+		snprintf(op_value, 4, "%d", 90 * op);
 
-	snprintf(rotate_str, 4, "%d", rotatearg);
 	snprintf(file_str, len, "%s", filename);
 
 	if ((pid = fork()) < 0) {
-		im_weprintf(w, "lossless rotate: fork failed:");
+		im_weprintf(w, "lossless %s: fork failed:", op_name);
 		return;
 	} else if (pid == 0) {
 
-		execlp("jpegtran", "jpegtran", "-copy", "all", "-rotate",
-				rotate_str, "-outfile", file_str, file_str, NULL);
+		execlp("jpegtran", "jpegtran", "-copy", "all", op_op, op_value,
+				"-outfile", file_str, file_str, NULL);
 
-		im_weprintf(w, "lossless rotate: Is 'jpegtran' installed? Failed to exec:");
+		im_weprintf(w, "lossless %s: Is 'jpegtran' installed? Failed to exec:", op_name);
 		return;
 	} else {
 		waitpid(pid, &status, 0);
 
 		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
 			im_weprintf(w,
-					"lossless rotate: Got exitcode %d from jpegtran."
+					"lossless %s: Got exitcode %d from jpegtran."
 					" Commandline was: "
-					"jpegtran -copy all -rotate %s -outfile %s %s",
-					status >> 8, rotate_str, file_str, file_str);
+					"jpegtran -copy all %s %s -outfile %s %s",
+					op_name, status >> 8, op_op, op_value, file_str, file_str);
 			return;
 		}
 	}
diff --git a/src/keyevents.c b/src/keyevents.c
index 12e9f73..617c2e9 100644
--- a/src/keyevents.c
+++ b/src/keyevents.c
@@ -285,6 +285,10 @@ void init_keyevents(void) {
 			cur_kb = &keys.orient_1;
 		else if (!strcmp(action, "orient_3"))
 			cur_kb = &keys.orient_3;
+		else if (!strcmp(action, "flip"))
+			cur_kb = &keys.flip;
+		else if (!strcmp(action, "mirror"))
+			cur_kb = &keys.mirror;
 		else if (!strcmp(action, "reload_minus"))
 			cur_kb = &keys.reload_minus;
 		else if (!strcmp(action, "reload_plus"))
@@ -637,10 +641,16 @@ void feh_event_handle_keypress(XEvent * ev)
 		winwidget_destroy(winwid);
 	}
 	else if (feh_is_kp(&keys.orient_1, keysym, state)) {
-		feh_edit_inplace_orient(winwid, 1);
+		feh_edit_inplace(winwid, 1);
 	}
 	else if (feh_is_kp(&keys.orient_3, keysym, state)) {
-		feh_edit_inplace_orient(winwid, 3);
+		feh_edit_inplace(winwid, 3);
+	}
+	else if (feh_is_kp(&keys.flip, keysym, state)) {
+		feh_edit_inplace(winwid, INPLACE_EDIT_FLIP);
+	}
+	else if (feh_is_kp(&keys.mirror, keysym, state)) {
+		feh_edit_inplace(winwid, INPLACE_EDIT_MIRROR);
 	}
 	else if (feh_is_kp(&keys.toggle_fullscreen, keysym, state)) {
 #ifdef HAVE_LIBXINERAMA
diff --git a/src/menu.c b/src/menu.c
index fe58760..ef30d03 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1351,7 +1351,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)
 			winwidget_size_to_image(m->fehwin);
 			break;
 		case CB_EDIT_ROTATE:
-			feh_edit_inplace_orient(m->fehwin, (int) data);
+			feh_edit_inplace(m->fehwin, (int) data);
 			break;
 		case CB_SAVE_IMAGE:
 			slideshow_save_image(m->fehwin);
diff --git a/src/options.h b/src/options.h
index 3c62441..bfcb94c 100644
--- a/src/options.h
+++ b/src/options.h
@@ -194,6 +194,8 @@ struct __fehkb {
 	struct __fehkey close;
 	struct __fehkey orient_1;
 	struct __fehkey orient_3;
+	struct __fehkey flip;
+	struct __fehkey mirror;
 	struct __fehkey toggle_fullscreen;
 	struct __fehkey reload_minus;
 	struct __fehkey reload_plus;
-- 
cgit v1.2.3