From 59451da3ac38599c7d5b1b2ced0f9368d6d63ba1 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Thu, 24 Aug 2017 15:03:07 -0500 Subject: [PATCH] softwrap: correctly move vertically through overwide tabs Don't skip rows that contain something when moving up, and do put the cursor in the desired column whenever possible when moving down. This fixes http://savannah.gnu.org/bugs/?51827 and fixes http://savannah.gnu.org/bugs/?51828. --- src/move.c | 60 +++++++++++++++++++++++++++++++++++++---------------- src/winio.c | 3 +++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/move.c b/src/move.c index c044aadf..d138356e 100644 --- a/src/move.c +++ b/src/move.c @@ -64,22 +64,51 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column) } } -/* Return the index in text that corresponds to the given column on the chunk - * starting on the given leftedge. If the index is on a tab and this tab - * starts on the preceding chunk, push the index one step forward. */ -size_t proper_x(const char *text, size_t leftedge, size_t 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. */ +size_t proper_x(filestruct *line, size_t *leftedge, bool forward, + size_t column, bool *shifted) { - size_t index = actual_x(text, column); + size_t index = actual_x(line->data, column); #ifndef NANO_TINY - if (ISSET(SOFTWRAP) && text[index] == '\t' && leftedge % tabsize != 0 && - column < leftedge + tabsize) + if (ISSET(SOFTWRAP) && line->data[index] == '\t' && (forward || + *leftedge / tabsize < (*leftedge + editwincols) / tabsize) && + *leftedge % tabsize != 0 && column < *leftedge + tabsize) { index++; + + *leftedge = leftedge_for(strnlenpt(line->data, index), line); + + if (shifted != NULL) + *shifted = TRUE; + } #endif return index; } +/* Adjust the values for current_x and placewewant in case we have landed in + * the middle of a tab that crosses a row boundary. */ +void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward) +{ + bool shifted = FALSE; + + openfile->current_x = proper_x(openfile->current, leftedge, forward, + actual_last_column(*leftedge, target), &shifted); + + /* If the index was incremented, try going to the target column. */ + if (shifted) { + size_t newer_x = actual_x(openfile->current->data, *leftedge + target); + + if (newer_x > openfile->current_x) + openfile->current_x = newer_x; + } + + openfile->placewewant = *leftedge + target; +} + /* Move up nearly one screenful. */ void do_page_up(void) { @@ -104,9 +133,7 @@ void do_page_up(void) return; } - openfile->placewewant = leftedge + target_column; - openfile->current_x = actual_x(openfile->current->data, - actual_last_column(leftedge, target_column)); + set_proper_index_and_pww(&leftedge, target_column, FALSE); /* Move the viewport so that the cursor stays immobile, if possible. */ adjust_viewport(STATIONARY); @@ -137,9 +164,7 @@ void do_page_down(void) return; } - openfile->placewewant = leftedge + target_column; - openfile->current_x = proper_x(openfile->current->data, leftedge, - actual_last_column(leftedge, target_column)); + set_proper_index_and_pww(&leftedge, target_column, TRUE); /* Move the viewport so that the cursor stays immobile, if possible. */ adjust_viewport(STATIONARY); @@ -363,7 +388,8 @@ void do_home(void) if (ISSET(SOFTWRAP)) { leftedge = leftedge_for(was_column, openfile->current); - leftedge_x = proper_x(openfile->current->data, leftedge, leftedge); + leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, + NULL); } if (ISSET(SMART_HOME)) { @@ -477,8 +503,7 @@ void do_up(bool scroll_only) if (go_back_chunks(1, &openfile->current, &leftedge) > 0) return; - openfile->current_x = actual_x(openfile->current->data, - actual_last_column(leftedge, target_column)); + set_proper_index_and_pww(&leftedge, target_column, FALSE); if (scroll_only) edit_scroll(UPWARD, 1); @@ -502,8 +527,7 @@ void do_down(bool scroll_only) if (go_forward_chunks(1, &openfile->current, &leftedge) > 0) return; - openfile->current_x = proper_x(openfile->current->data, leftedge, - actual_last_column(leftedge, target_column)); + set_proper_index_and_pww(&leftedge, target_column, TRUE); if (scroll_only) edit_scroll(DOWNWARD, 1); diff --git a/src/winio.c b/src/winio.c index 0f9564c7..4fe9db06 100644 --- a/src/winio.c +++ b/src/winio.c @@ -3089,6 +3089,9 @@ size_t leftedge_for(size_t column, filestruct *line) { size_t leftedge; + if (!ISSET(SOFTWRAP)) + return 0; + get_chunk_and_edge(column, line, &leftedge); return leftedge;