softwrap: improve Up and Down's behavior with softwrapped chunks

Use go_back_chunks() and go_forward_chunks() in do_up() and do_down()
(instead of using a special and complicated computation in do_down())
so that they now properly move vertically to the previous/next chunk
in softwrap mode.  This also means that do_left() and do_right() will
now properly move vertically at actual line boundaries.
master
David Lawrence Ramsey 2017-01-20 11:11:17 -06:00 committed by Benno Schulenberg
parent 56402e7589
commit eb647dfb44
1 changed files with 49 additions and 62 deletions

View File

@ -455,22 +455,33 @@ void do_end_void(void)
do_end(TRUE); do_end(TRUE);
} }
/* If scroll_only is FALSE, move up one line. If scroll_only is TRUE, /* Move the cursor to the preceding line or chunk. If scroll_only is TRUE,
* scroll up one line without scrolling the cursor. */ * also scroll the screen one row, so the cursor stays in the same spot. */
void do_up(bool scroll_only) void do_up(bool scroll_only)
{ {
size_t was_column = xplustabs(); size_t was_column = xplustabs();
filestruct *was_current = openfile->current;
size_t leftedge = 0;
size_t target_column = openfile->placewewant;
/* If we're at the top of the file, or if scroll_only is TRUE and /* When just scrolling and the top of the file is onscreen, get out. */
* the top of the file is onscreen, get out. */ if (scroll_only && openfile->edittop == openfile->fileage)
if (openfile->current == openfile->fileage || return;
(scroll_only && openfile->edittop == openfile->fileage))
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
leftedge = (openfile->placewewant / editwincols) * editwincols;
target_column = openfile->placewewant % editwincols;
}
#endif
/* Move up one line or chunk. */
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
return; return;
/* Move the current line of the edit window up. */
openfile->current = openfile->current->prev;
openfile->current_x = actual_x(openfile->current->data, openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant); leftedge + target_column);
openfile->placewewant = leftedge + target_column;
/* When the cursor was on the first line of the edit window (or when just /* When the cursor was on the first line of the edit window (or when just
* scrolling without moving the cursor), scroll the edit window up -- one * scrolling without moving the cursor), scroll the edit window up -- one
@ -481,8 +492,11 @@ void do_up(bool scroll_only)
/* If the lines weren't already redrawn, see if they need to be. */ /* If the lines weren't already redrawn, see if they need to be. */
if (openfile->current_y > 0) { if (openfile->current_y > 0) {
/* Redraw the prior line if it was horizontally scrolled. */ /* Redraw the prior line if it's not actually the same line as the
if (line_needs_update(was_column, 0)) * current one (which it might be in softwrap mode, if we moved just
* one chunk) and the line was horizontally scrolled. */
if (openfile->current != was_current
&& line_needs_update(was_column, 0))
update_line(openfile->current->next, 0); update_line(openfile->current->next, 0);
/* Redraw the current line if it needs to be horizontally scrolled. */ /* Redraw the current line if it needs to be horizontally scrolled. */
if (line_needs_update(0, xplustabs())) if (line_needs_update(0, xplustabs()))
@ -490,77 +504,50 @@ void do_up(bool scroll_only)
} }
} }
/* Move up one line. */ /* Move up one line or chunk. */
void do_up_void(void) void do_up_void(void)
{ {
do_up(FALSE); do_up(FALSE);
} }
/* If scroll_only is FALSE, move down one line. If scroll_only is TRUE, /* Move the cursor to next line or chunk. If scroll_only is TRUE, also
* scroll down one line without scrolling the cursor. */ * scroll the screen one row, so the cursor stays in the same spot. */
void do_down(bool scroll_only) void do_down(bool scroll_only)
{ {
#ifndef NANO_TINY
int amount = 0, enough;
filestruct *topline;
#endif
size_t was_column = xplustabs(); size_t was_column = xplustabs();
filestruct *was_current = openfile->current;
/* If we're at the bottom of the file, get out. */ size_t leftedge = 0;
if (openfile->current == openfile->filebot) size_t target_column = openfile->placewewant;
return;
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(SOFTWRAP)) { if (ISSET(SOFTWRAP)) {
/* Compute the number of lines to scroll. */ leftedge = (openfile->placewewant / editwincols) * editwincols;
amount = strlenpt(openfile->current->data) / editwincols - target_column = openfile->placewewant % editwincols;
xplustabs() / editwincols +
strlenpt(openfile->current->next->data) / editwincols +
openfile->current_y - editwinrows + 2;
topline = openfile->edittop;
/* Reduce the amount when there are overlong lines at the top. */
for (enough = 1; enough < amount; enough++) {
amount -= strlenpt(topline->data) / editwincols;
if (amount > 0)
topline = topline->next;
if (amount < enough) {
amount = enough;
break;
}
}
} }
#endif #endif
/* Move to the next line in the file. */ /* Move down one line or chunk. */
openfile->current = openfile->current->next; if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
return;
openfile->current_x = actual_x(openfile->current->data, openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant); leftedge + target_column);
openfile->placewewant = leftedge + target_column;
/* When the cursor was on the last line of the edit window (or when just /* When the cursor was on the last line of the edit window (or when just
* scrolling without moving the cursor), scroll the edit window down -- one * scrolling without moving the cursor), scroll the edit window down -- one
* line if we're in smooth scrolling mode, and half a page otherwise. */ * line if we're in smooth scrolling mode, and half a page otherwise. */
#ifndef NANO_TINY if (openfile->current_y == editwinrows - 1 || scroll_only)
if (openfile->current_y == editwinrows - 1 || amount > 0 || scroll_only) {
if (amount < 1 || scroll_only)
amount = 1;
edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ? edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
amount : editwinrows / 2 + 1); 1 : editwinrows / 2 + 1);
if (ISSET(SOFTWRAP)) {
refresh_needed = TRUE;
return;
}
}
#else
if (openfile->current_y == editwinrows - 1)
edit_scroll(DOWNWARD, editwinrows / 2 + 1);
#endif
/* If the lines weren't already redrawn, see if they need to be. */ /* If the lines weren't already redrawn, see if they need to be. */
if (openfile->current_y < editwinrows - 1) { if (openfile->current_y < editwinrows - 1) {
/* Redraw the prior line if it was horizontally scrolled. */ /* Redraw the prior line if it's not actually the same line as the
if (line_needs_update(was_column, 0)) * current one (which it might be in softwrap mode, if we moved just
* one chunk) and the line was horizontally scrolled. */
if (openfile->current != was_current &&
line_needs_update(was_column, 0))
update_line(openfile->current->prev, 0); update_line(openfile->current->prev, 0);
/* Redraw the current line if it needs to be horizontally scrolled. */ /* Redraw the current line if it needs to be horizontally scrolled. */
if (line_needs_update(0, xplustabs())) if (line_needs_update(0, xplustabs()))
@ -568,20 +555,20 @@ void do_down(bool scroll_only)
} }
} }
/* Move down one line. */ /* Move down one line or chunk. */
void do_down_void(void) void do_down_void(void)
{ {
do_down(FALSE); do_down(FALSE);
} }
#ifndef NANO_TINY #ifndef NANO_TINY
/* Scroll up one line without scrolling the cursor. */ /* Scroll up one line or chunk without scrolling the cursor. */
void do_scroll_up(void) void do_scroll_up(void)
{ {
do_up(TRUE); do_up(TRUE);
} }
/* Scroll down one line without scrolling the cursor. */ /* Scroll down one line or chunk without scrolling the cursor. */
void do_scroll_down(void) void do_scroll_down(void)
{ {
do_down(TRUE); do_down(TRUE);