aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Bruce Hill <bruce@bruce-hill.com>2019-05-09 19:14:24 -0700
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2019-05-22 08:48:44 +0530
commita75223589212985b0fcd42395b841e409e779cbb (patch)
tree29de175e6fbc236fea643aa2d1b109239548907a
parent9dc3976533fd468557df4d375b2c3b3530fff695 (diff)
downloadnnn-a75223589212985b0fcd42395b841e409e779cbb.tar.gz
Alternate scrolling rules.
-rw-r--r--src/nnn.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/src/nnn.c b/src/nnn.c
index 75df0e7..f2741b6 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -473,6 +473,7 @@ static void redraw(char *path);
static int spawn(char *file, char *arg1, char *arg2, const char *dir, uchar flag);
static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
static int dentfind(const char *fname, int n);
+static void move_cursor(int target, int ignore_scrolloff);
/* Functions */
@@ -1656,7 +1657,7 @@ end:
if (*ch != '\t')
g_ctx[cfg.curctx].c_fltr[0] = g_ctx[cfg.curctx].c_fltr[1] = '\0';
- curscroll = MAX(0, cur - SCROLLOFF);
+ move_cursor(cur, 0);
curs_set(FALSE);
settimeout();
@@ -2881,11 +2882,33 @@ static void populate(char *path, char *lastname)
/* Find cur from history */
/* No NULL check for lastname, always points to an array */
if (!*lastname)
- cur = 0;
+ move_cursor(0, 0);
else
- cur = dentfind(lastname, ndents);
+ move_cursor(dentfind(lastname, ndents), 0);
+}
- curscroll = MAX(0, cur - SCROLLOFF);
+static void move_cursor(int target, int ignore_scrolloff)
+{
+ int delta, scrolloff, onscreen = xlines - 4;
+ target = MAX(0, MIN(ndents - 1, target));
+ delta = target - cur;
+ cur = target;
+ if (!ignore_scrolloff) {
+ scrolloff = MIN(SCROLLOFF, onscreen >> 1);
+ /*
+ * When ignore_scrolloff is 1, the cursor can jump into the scrolloff
+ * margin area, but when ignore_scrolloff is 0, act like a boa
+ * constrictor and squeeze the cursor towards the middle region of the
+ * screen by allowing it to move inward and disallowing it to move
+ * outward (deeper into the scrolloff margin area).
+ */
+ if (cur < curscroll + scrolloff && delta < 0)
+ curscroll += delta;
+ else if (cur > curscroll + onscreen - scrolloff - 1 && delta > 0)
+ curscroll += delta;
+ }
+ curscroll = MIN(curscroll, MIN(cur, ndents - onscreen));
+ curscroll = MAX(curscroll, MAX(cur - (onscreen - 1), 0));
}
static void redraw(char *path)
@@ -2895,7 +2918,6 @@ static void redraw(char *path)
int ncols = (xcols <= PATH_MAX) ? xcols : PATH_MAX;
int lastln = xlines, onscreen = xlines - 4;
- int scrolloff = MIN(SCROLLOFF, onscreen >> 1);
int i, attrs;
char buf[12];
char c;
@@ -2905,12 +2927,8 @@ static void redraw(char *path)
/* Clear screen */
erase();
- if (ndents <= onscreen)
- curscroll = 0;
- else if (cur < curscroll + scrolloff)
- curscroll = MAX(0, cur - scrolloff);
- else if (cur > curscroll + onscreen - scrolloff - 1)
- curscroll = MIN(ndents - onscreen, cur - onscreen + scrolloff + 1);
+ /* Enforce scroll/cursor invariants */
+ move_cursor(cur, 1);
#ifdef DIR_LIMITED_COPY
if (cfg.copymode)
@@ -3168,7 +3186,7 @@ nochange:
if (r >= ndents)
goto nochange;
- cur = r;
+ move_cursor(r, 1);
// Single click just selects, double click also opens
if (event.bstate != BUTTON1_DOUBLE_CLICKED)
@@ -3264,42 +3282,38 @@ nochange:
goto nochange;
}
case SEL_NEXT:
- if (cur < ndents - 1)
- ++cur;
- else if (ndents)
- /* Roll over, set cursor to first entry */
- cur = 0;
+ if (ndents)
+ move_cursor((cur + 1) % ndents, 0);
break;
case SEL_PREV:
- if (cur > 0)
- --cur;
- else if (ndents)
- /* Roll over, set cursor to last entry */
- cur = ndents - 1;
+ if (ndents)
+ move_cursor((cur + ndents - 1) % ndents, 0);
break;
case SEL_PGDN: // fallthrough
+ onscreen = xlines - 4;
+ move_cursor(curscroll + (onscreen - 1), 1);
+ curscroll += onscreen - 1;
+ break;
case SEL_CTRL_D:
onscreen = xlines - 4;
- r = sel == SEL_PGDN ? onscreen - 1 : onscreen >> 1;
- curscroll = MIN(ndents - onscreen, curscroll + r);
- cur = (curscroll == ndents - onscreen) ? cur + r :
- curscroll + MIN(SCROLLOFF, onscreen >> 1);
- cur = MIN(ndents - 1, cur);
+ move_cursor(curscroll + (onscreen - 1), 1);
+ curscroll += onscreen >> 1;
break;
case SEL_PGUP: // fallthrough
+ onscreen = xlines - 4;
+ move_cursor(curscroll, 1);
+ curscroll -= onscreen - 1;
+ break;
case SEL_CTRL_U:
onscreen = xlines - 4;
- r = sel == SEL_PGUP ? onscreen - 1 : onscreen >> 1;
- curscroll = MAX(0, curscroll - r);
- cur = (curscroll == 0) ? cur - r :
- curscroll + onscreen - MIN(SCROLLOFF, onscreen >> 1) - 1;
- cur = MAX(0, cur);
+ move_cursor(curscroll, 1);
+ curscroll -= onscreen >> 1;
break;
case SEL_HOME:
- cur = 0;
+ move_cursor(0, 1);
break;
case SEL_END:
- cur = ndents - 1;
+ move_cursor(ndents - 1, 1);
break;
case SEL_CDHOME: // fallthrough
case SEL_CDBEGIN: // fallthrough
@@ -3797,7 +3811,7 @@ nochange:
/* Don't optimize cur if filtering is on */
if (!cfg.filtermode && cur && access(newpath, F_OK) == -1)
- --cur;
+ move_cursor(cur - 1, 0);
/* We reduce cur only if it is > 0, so it's at least 0 */
copycurname();