scrolling: don't scroll too much when having to bridge blank lines

Add a third mode of scrolling, FLOWING, besides CENTERING and STATIONARY.
This is used for word and paragraph jumping (and for bracket matching,
but that worked correctly already), and only when focusing is FALSE.

The new mode prevents the screen from scrolling too many lines when
there are several blank lines at the bottom of the edit window and
the next word or paragraph is out of view.

This fixes https://savannah.gnu.org/bugs/?47194.
master
Benno Schulenberg 2016-04-07 13:58:51 +02:00
parent d851ccdd41
commit cb17732ac2
6 changed files with 31 additions and 24 deletions

View File

@ -96,7 +96,7 @@ void do_page_up(void)
#endif
/* Scroll the edit window up a page. */
edit_update(NONE);
edit_update(STATIONARY);
}
/* Move down one page. */
@ -136,7 +136,7 @@ void do_page_down(void)
openfile->placewewant);
/* Scroll the edit window down a page. */
edit_update(NONE);
edit_update(STATIONARY);
}
#ifndef DISABLE_JUSTIFY

View File

@ -404,7 +404,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
/* If the top of the edit window was inside the old partition, put
* it in range of current. */
if (edittop_inside)
edit_update(NONE);
edit_update(STATIONARY);
/* Renumber starting with the beginning line of the old
* partition. */

View File

@ -176,7 +176,7 @@ typedef enum {
} scroll_dir;
typedef enum {
CENTER, NONE
CENTERING, FLOWING, STATIONARY
} update_type;
typedef enum {

View File

@ -958,7 +958,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
openfile->placewewant = column - 1;
/* Put the top line of the edit window in range of the current line. */
edit_update(CENTER);
edit_update(CENTERING);
/* When in interactive mode, update the screen. */
if (interactive) {

View File

@ -2831,7 +2831,7 @@ const char *do_alt_speller(char *tempfile_name)
/* Go back to the old position. */
goto_line_posx(lineno_save, current_x_save);
openfile->current_y = current_y_save;
edit_update(NONE);
edit_update(STATIONARY);
/* Stat the temporary file again, and mark the buffer as modified only
* if this file was changed since it was written. */
@ -3310,7 +3310,7 @@ void do_formatter(void)
goto_line_posx(lineno_save, current_x_save);
openfile->current_y = current_y_save;
openfile->placewewant = pww_save;
edit_update(NONE);
edit_update(STATIONARY);
set_modified();

View File

@ -2963,7 +2963,7 @@ void edit_redraw(filestruct *old_current, size_t pww_save)
/* If the current line is offscreen, scroll until it's onscreen. */
if (openfile->current->lineno >= openfile->edittop->lineno + maxrows ||
openfile->current->lineno < openfile->edittop->lineno)
edit_update((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTER : NONE);
edit_update((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING);
#ifndef NANO_TINY
/* If the mark is on, update all lines between old_current and current. */
@ -3005,7 +3005,7 @@ void edit_refresh(void)
#endif
/* Make sure the current line is on the screen. */
edit_update((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTER : NONE);
edit_update((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
}
foo = openfile->edittop;
@ -3027,26 +3027,33 @@ void edit_refresh(void)
wnoutrefresh(edit);
}
/* Move edittop to put it in range of current, keeping current in the
* same place. location determines how we move it: if it's CENTER, we
* center current, and if it's NONE, we put current current_y lines
* below edittop. */
void edit_update(update_type location)
/* Move edittop so that current is on the screen. manner says how it
* should be moved: CENTERING means that current should end up in the
* middle of the screen, STATIONARY means that it should stay at the
* same vertical position, and FLOWING means that it should scroll no
* more than needed to bring current into view. */
void edit_update(update_type manner)
{
filestruct *foo = openfile->current;
int goal;
/* If location is CENTER, we move edittop up (editwinrows / 2)
* lines. This puts current at the center of the screen. If
* location is NONE, we move edittop up current_y lines if current_y
* is in range of the screen, 0 lines if current_y is less than 0,
* or (editwinrows - 1) lines if current_y is greater than
* (editwinrows - 1). This puts current at the same place on the
* screen as before, or at the top or bottom of the screen if
* edittop is beyond either. */
if (location == CENTER)
/* If manner is CENTERING, move edittop half the number of window
* lines back from current. If manner is STATIONARY, move edittop
* back current_y lines if current_y is in range of the screen,
* 0 lines if current_y is below zero, or (editwinrows - 1) lines
* if current_y is too big. This puts current at the same place
* on the screen as before, or at the top or bottom if current_y is
* beyond either. If manner is FLOWING, move edittop back 0 lines
* or (editwinrows - 1) lines, depending or where current has moved.
* This puts the cursor on the first or the last line. */
if (manner == CENTERING)
goal = editwinrows / 2;
else {
else if (manner == FLOWING) {
if (openfile->current->lineno < openfile->edittop->lineno)
goal = 0;
else
goal = editwinrows - 1;
} else {
goal = openfile->current_y;
/* Limit goal to (editwinrows - 1) lines maximum. */