From 380ad30a53b25644f96b3fad07ee7285537b132e Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Wed, 18 Jan 2017 20:31:33 -0600
Subject: [PATCH] softwrap: account for softwrap when checking whether current
 is offscreen

Add the new functions current_is_above_screen() (which doesn't account
for softwrapped chunks yet, but will when we can scroll edittop partially
off the screen, which is forthcoming), current_is_below_screen() (which
determines whether current[current_x] is past the softwrapped chunk at
the bottom of the screen), and current_is_offscreen() (the union of the
previous two functions).

edit_redraw() and edit_refresh() now use current_is_offscreen() to check
whether they should adjust the viewport, and adjust_viewport() now uses
current_is_above_screen() to determine whether current is on or below
the screen in FLOWING mode.
---
 src/proto.h |  3 +++
 src/winio.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/src/proto.h b/src/proto.h
index c7eeeb93..1415af73 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -711,6 +711,9 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge);
 int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge);
 bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
 void edit_scroll(scroll_dir direction, int nrows);
+bool current_is_above_screen(void);
+bool current_is_below_screen(void);
+bool current_is_offscreen(void);
 void edit_redraw(filestruct *old_current);
 void edit_refresh(void);
 void adjust_viewport(update_type location);
diff --git a/src/winio.c b/src/winio.c
index 39538644..84a7e9b0 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -2946,6 +2946,41 @@ void edit_scroll(scroll_dir direction, int nrows)
     compute_maxlines();
 }
 
+/* Return TRUE if current[current_x] is above the top of the screen, and FALSE
+ * otherwise. */
+bool current_is_above_screen(void)
+{
+    return (openfile->current->lineno < openfile->edittop->lineno);
+}
+
+/* Return TRUE if current[current_x] is below the bottom of the screen, and
+ * FALSE otherwise. */
+bool current_is_below_screen(void)
+{
+#ifndef NANO_TINY
+    if (ISSET(SOFTWRAP)) {
+	filestruct *line = openfile->edittop;
+	size_t leftedge = 0;
+
+	/* If current[current_x] is more than a screen's worth of lines after
+	 * edittop, it's below the screen. */
+	return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 &&
+			(line->lineno < openfile->current->lineno ||
+			(line->lineno == openfile->current->lineno &&
+			leftedge < (xplustabs() / editwincols) * editwincols)));
+    } else
+#endif
+	return (openfile->current->lineno >=
+			openfile->edittop->lineno + editwinrows);
+}
+
+/* Return TRUE if current[current_x] is offscreen relative to edittop, and
+ * FALSE otherwise. */
+bool current_is_offscreen(void)
+{
+    return (current_is_above_screen() || current_is_below_screen());
+}
+
 /* Update any lines between old_current and current that need to be
  * updated.  Use this if we've moved without changing any text. */
 void edit_redraw(filestruct *old_current)
@@ -2955,12 +2990,7 @@ void edit_redraw(filestruct *old_current)
     openfile->placewewant = xplustabs();
 
     /* If the current line is offscreen, scroll until it's onscreen. */
-    if (openfile->current->lineno >= openfile->edittop->lineno + maxlines ||
-#ifndef NANO_TINY
-		(openfile->current->lineno == openfile->edittop->lineno + maxlines - 1 &&
-		ISSET(SOFTWRAP) && strlenpt(openfile->current->data) >= editwincols) ||
-#endif
-		openfile->current->lineno < openfile->edittop->lineno) {
+    if (current_is_offscreen()) {
 	adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING);
 	refresh_needed = TRUE;
 	return;
@@ -3003,8 +3033,7 @@ void edit_refresh(void)
     compute_maxlines();
 
     /* If the current line is out of view, get it back on screen. */
-    if (openfile->current->lineno < openfile->edittop->lineno ||
-		openfile->current->lineno >= openfile->edittop->lineno + maxlines) {
+    if (current_is_offscreen()) {
 #ifdef DEBUG
 	fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and maxlines = %d\n",
 		(long)openfile->current->lineno, (long)openfile->edittop->lineno, maxlines);
@@ -3055,7 +3084,7 @@ void adjust_viewport(update_type manner)
     if (manner == CENTERING)
 	goal = editwinrows / 2;
     else if (manner == FLOWING) {
-	if (openfile->current->lineno >= openfile->edittop->lineno) {
+	if (!current_is_above_screen()) {
 	    goal = editwinrows - 1;
 #ifndef NANO_TINY
 	    if (ISSET(SOFTWRAP))
-- 
GitLab