From 7a3a45e6accf9b7d4f589c2972ed1d74117f1309 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@telfort.nl>
Date: Sat, 30 Sep 2017 21:48:05 +0200
Subject: [PATCH] moving: prevent the cursor sticking on or skipping over
 overwide tabs

When we've landed on a tab and we are moving down and the tab starts
before the current chunk, then push the index forward -- otherwise we
would not advance.  When instead we're moving up and the end of the
preceding row is on the same tab as the target column AND the end of
the current row is not on that same tab, then there is some character
on this row that we can put the cursor on, so push the index forward
-- otherwise we would skip a usable row.

This fixes https://savannah.gnu.org/bugs/?52125
and fixes https://savannah.gnu.org/bugs/?52139.
---
 src/move.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/move.c b/src/move.c
index b36b4bca..9e25fe9a 100644
--- a/src/move.c
+++ b/src/move.c
@@ -65,18 +65,19 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
 }
 
 /* Return the index in line->data that corresponds to the given column on the
- * chunk that starts at the given leftedge.  If the index lands on a tab, and
- * this tab starts on an earlier chunk, and the tab ends on this row OR we're
- * going forward, then increment the index and recalculate leftedge. */
+ * chunk that starts at the given leftedge.  If the target column has landed
+ * on a tab, prevent the cursor from falling back a row when moving forward,
+ * or from skipping a row when moving backward, by incrementing the index. */
 size_t proper_x(filestruct *line, size_t *leftedge, bool forward,
 		size_t column, bool *shifted)
 {
     size_t index = actual_x(line->data, column);
 
 #ifndef NANO_TINY
-    if (ISSET(SOFTWRAP) && line->data[index] == '\t' && (forward ||
-		*leftedge / tabsize < (*leftedge + editwincols) / tabsize) &&
-		*leftedge % tabsize != 0 && column < *leftedge + tabsize) {
+    if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
+		((forward && strnlenpt(line->data, index) < *leftedge) ||
+		(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
+		column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
 	index++;
 
 	*leftedge = leftedge_for(strnlenpt(line->data, index), line);
-- 
GitLab