From 81963c7b44194be63479299f217e97e2d0c48db5 Mon Sep 17 00:00:00 2001
From: Daniel Friesel <derf@finalrewind.org>
Date: Thu, 8 Mar 2018 19:42:35 +0100
Subject: add (experimental and still slightly buggy) --inner-geometry feature

See #278
---
 src/options.c   |  5 +++++
 src/options.h   |  5 +++++
 src/winwidget.c | 26 ++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/src/options.c b/src/options.c
index 3d11482..0db5aae 100644
--- a/src/options.c
+++ b/src/options.c
@@ -416,6 +416,7 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
 		{"no-recursive"  , 0, 0, 241},
 		{"cache-size"    , 1, 0, 243},
 		{"version-sort"  , 0, 0, 246},
+		{"inner-geometry", 1, 0, 247},
 		{0, 0, 0, 0}
 	};
 	int optch = 0, cmdx = 0;
@@ -784,6 +785,10 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
 		case 246:
 			opt.version_sort = 1;
 			break;
+		case 247:
+			opt.inner_geom_flags = XParseGeometry(optarg, &opt.inner_geom_x,
+					&opt.inner_geom_y, &opt.inner_geom_w, &opt.inner_geom_h);
+			break;
 		default:
 			break;
 		}
diff --git a/src/options.h b/src/options.h
index d4de3c5..d4ffbeb 100644
--- a/src/options.h
+++ b/src/options.h
@@ -111,6 +111,11 @@ struct __fehoptions {
 	int geom_y;
 	unsigned int geom_w;
 	unsigned int geom_h;
+	int inner_geom_flags;
+	int inner_geom_x;
+	int inner_geom_y;
+	unsigned int inner_geom_w;
+	unsigned int inner_geom_h;
 	int default_zoom;
 	int zoom_mode;
 	unsigned char adjust_reload;
diff --git a/src/winwidget.c b/src/winwidget.c
index bb6181a..7b8a9dc 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -555,6 +555,32 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
 		winwid->im_y = (int) (winwid->h - (winwid->im_h * winwid->zoom)) >> 1;
 	}
 
+	/*
+	 * Adjust X/Y offset if the image is larger than the window and
+	 * --inner-geometry is set. This will cause odd behaviour when
+	 * zooming an already large image in --inner-geometry mode, but in most
+	 * cases this should be what the user wants. Plus, it doesn't require
+	 * fiddling around in two or three places above, so it's the best
+	 * solution considering a future refactoring of this function.
+	 */
+
+	if (need_center || resize) {
+		if ((opt.inner_geom_flags & XValue) && (winwid->im_w * winwid->zoom) > winwid->w) {
+			if (opt.inner_geom_flags & XNegative) {
+				winwid->im_x = winwid->w - (winwid->im_w * winwid->zoom) - opt.inner_geom_x;
+			} else {
+				winwid->im_x = - opt.inner_geom_x * winwid->zoom;
+			}
+		}
+		if ((opt.inner_geom_flags & YValue) && (winwid->im_h * winwid->zoom) > winwid->h) {
+			if (opt.inner_geom_flags & YNegative) {
+				winwid->im_y = winwid->h - (winwid->im_h * winwid->zoom) - opt.inner_geom_y;
+			} else {
+				winwid->im_y = - opt.inner_geom_y * winwid->zoom;
+			}
+		}
+	}
+
 	/* Now we ensure only to render the area we're looking at */
 	dx = winwid->im_x;
 	dy = winwid->im_y;
-- 
cgit v1.2.3