From acdc20228699e2ad72638fcd3ad8f90dd0e8f37f Mon Sep 17 00:00:00 2001
From: David Lawrence Ramsey <pooka109@gmail.com>
Date: Fri, 18 Aug 2017 18:59:38 -0500
Subject: [PATCH] display: revamp how screen updates are done in the movement
 code

If tabs are wider than the screen, all the assumptions that one chunk is
one line go out the window, so use edit_redraw() after edit_scroll()
instead.

This fixes http://savannah.gnu.org/bugs/?51776.
---
 src/move.c  | 86 ++++++++++++-------------------------------------------------
 src/proto.h |  2 ++
 2 files changed, 18 insertions(+), 70 deletions(-)

diff --git a/src/move.c b/src/move.c
index a3dd6e9d..c7d612b9 100644
--- a/src/move.c
+++ b/src/move.c
@@ -447,8 +447,6 @@ void do_end(void)
  * also scroll the screen one row, so the cursor stays in the same spot. */
 void do_up(bool scroll_only)
 {
-    filestruct *was_current = openfile->current;
-    size_t was_column = xplustabs();
     size_t leftedge, target_column;
 
     /* When just scrolling and the top of the file is onscreen, get out. */
@@ -462,36 +460,24 @@ void do_up(bool scroll_only)
     if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
 	return;
 
-    openfile->placewewant = leftedge + target_column;
     openfile->current_x = actual_x(openfile->current->data,
 				actual_last_column(leftedge, target_column));
 
-    /* When the cursor was on the first line of the edit window (or when just
+    /* When the cursor is above the first line of the edit window (or when just
      * scrolling without moving the cursor), scroll the edit window up -- one
      * line if we're in smooth scrolling mode, and half a page otherwise. */
-    if (openfile->current_y == 0 || scroll_only)
+    if (current_is_above_screen() || scroll_only)
 	edit_scroll(UPWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
 				1 : editwinrows / 2 + 1);
 
-    if (openfile->current_y > 0) {
-	/* Redraw the prior line if it's not offscreen, and it's not the same
-	 * line as the current one, and the line was horizontally scrolled. */
-	if ((!scroll_only || openfile->current_y < editwinrows - 1) &&
-			openfile->current != was_current &&
-			line_needs_update(was_column, 0))
-	    update_line(openfile->current->next, 0);
-	/* Redraw the current line if it needs to be horizontally scrolled. */
-	if (line_needs_update(0, xplustabs()))
-	    update_line(openfile->current, openfile->current_x);
-    }
+    edit_redraw(openfile->current, FLOWING);
+    openfile->placewewant = leftedge + target_column;
 }
 
 /* Move the cursor to next line or chunk.  If scroll_only is TRUE, also
  * scroll the screen one row, so the cursor stays in the same spot. */
 void do_down(bool scroll_only)
 {
-    filestruct *was_current = openfile->current;
-    size_t was_column = xplustabs();
     size_t leftedge, target_column;
 
     get_edge_and_target(&leftedge, &target_column);
@@ -500,28 +486,18 @@ void do_down(bool scroll_only)
     if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
 	return;
 
-    openfile->placewewant = leftedge + target_column;
     openfile->current_x = actual_x(openfile->current->data,
 				actual_last_column(leftedge, target_column));
 
-    /* When the cursor was on the last line of the edit window (or when just
+    /* When the cursor is below the last line of the edit window (or when just
      * scrolling without moving the cursor), scroll the edit window down -- one
      * line if we're in smooth scrolling mode, and half a page otherwise. */
-    if (openfile->current_y == editwinrows - 1 || scroll_only)
+    if (current_is_below_screen() || scroll_only)
 	edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
 				1 : editwinrows / 2 + 1);
 
-    if (openfile->current_y < editwinrows - 1) {
-	/* Redraw the prior line if it's not offscreen, and it's not the same
-	 * line as the current one, and the line was horizontally scrolled. */
-	if ((!scroll_only || openfile->current_y > 0) &&
-			openfile->current != was_current &&
-			line_needs_update(was_column, 0))
-	    update_line(openfile->current->prev, 0);
-	/* Redraw the current line if it needs to be horizontally scrolled. */
-	if (line_needs_update(0, xplustabs()))
-	    update_line(openfile->current, openfile->current_x);
-    }
+    edit_redraw(openfile->current, FLOWING);
+    openfile->placewewant = leftedge + target_column;
 }
 
 /* Move up one line or chunk. */
@@ -553,12 +529,6 @@ void do_scroll_down(void)
 /* Move left one character. */
 void do_left(void)
 {
-    size_t was_column = xplustabs();
-#ifndef NANO_TINY
-    filestruct *was_current = openfile->current;
-    size_t was_chunk = chunk_for(was_column, was_current);
-#endif
-
     if (openfile->current_x > 0)
 	openfile->current_x = move_mbleft(openfile->current->data,
 						openfile->current_x);
@@ -570,34 +540,19 @@ void do_left(void)
 	return;
     }
 
-    openfile->placewewant = xplustabs();
-
 #ifndef NANO_TINY
-    /* If we were on the first line of the edit window, and we changed chunk,
-     * we're now above the first line of the edit window, so scroll up. */
-    if (ISSET(SOFTWRAP) && openfile->current_y == 0 &&
-		openfile->current == was_current &&
-		chunk_for(openfile->placewewant,
-				openfile->current) != was_chunk) {
+    /* If we're above the first line of the edit window from changing chunk,
+     * scroll up. */
+    if (ISSET(SOFTWRAP) && current_is_above_screen())
 	edit_scroll(UPWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
-	return;
-    }
 #endif
 
-    /* Update current if the mark is on or it has changed "page". */
-    if (line_needs_update(was_column, openfile->placewewant))
-	update_line(openfile->current, openfile->current_x);
+    edit_redraw(openfile->current, FLOWING);
 }
 
 /* Move right one character. */
 void do_right(void)
 {
-    size_t was_column = xplustabs();
-#ifndef NANO_TINY
-    filestruct *was_current = openfile->current;
-    size_t was_chunk = chunk_for(was_column, was_current);
-#endif
-
     if (openfile->current->data[openfile->current_x] != '\0')
 	openfile->current_x = move_mbright(openfile->current->data,
 						openfile->current_x);
@@ -609,21 +564,12 @@ void do_right(void)
 	return;
     }
 
-    openfile->placewewant = xplustabs();
-
 #ifndef NANO_TINY
-    /* If we were on the last line of the edit window, and we changed chunk,
-     * we're now below the first line of the edit window, so scroll down. */
-    if (ISSET(SOFTWRAP) && openfile->current_y == editwinrows - 1 &&
-		openfile->current == was_current &&
-		chunk_for(openfile->placewewant,
-				openfile->current) != was_chunk) {
+    /* If we're below the last line of the edit window from changing chunk,
+     * scroll down. */
+    if (ISSET(SOFTWRAP) && current_is_below_screen())
 	edit_scroll(DOWNWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
-	return;
-    }
 #endif
 
-    /* Update current if the mark is on or it has changed "page". */
-    if (line_needs_update(was_column, openfile->placewewant))
-	update_line(openfile->current, openfile->current_x);
+    edit_redraw(openfile->current, FLOWING);
 }
diff --git a/src/proto.h b/src/proto.h
index 0b63f179..39495d0d 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -674,6 +674,8 @@ size_t number_of_chunks_in(filestruct *line);
 void ensure_firstcolumn_is_aligned(void);
 #endif
 size_t actual_last_column(size_t leftedge, size_t column);
+bool current_is_above_screen(void);
+bool current_is_below_screen(void);
 void edit_redraw(filestruct *old_current, update_type manner);
 void edit_refresh(void);
 void adjust_viewport(update_type location);
-- 
2.14.1

