Modify line number arithmetic to no longer assume linear increments.

When adding folding lines, the lines drawn on screen are no longer
guaranteed to increment one by one. There could be a large skip when
handling folded segments. So instances where the codebase assumed
'openfile->current->lineno - edittop->lineno' would yield the position
on screen of the current line needed to be modified. Similar problems
existed in many places so a function 'get_row_from_edittop' handles
finding the current position of a line in relation to 'edittop'.

Signed-off-by: rexy712 <rexy712@protonmail.com>
This commit is contained in:
rexy712 2023-04-06 11:51:53 -07:00
parent a299827554
commit 90dac326c1
3 changed files with 107 additions and 29 deletions

View File

@ -235,19 +235,29 @@ void to_para_end(void)
void to_prev_block(void)
{
linestruct *was_current = openfile->current;
linestruct *line_step = get_prev_visible_line(openfile->current);
bool is_text = FALSE, seen_text = FALSE;
/* Skip backward until first blank line after some nonblank line(s). */
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
openfile->current = openfile->current->prev;
while (line_step != NULL && (!seen_text || is_text)) {
openfile->current = line_step;
line_step = get_prev_visible_line(line_step);
#ifdef ENABLE_FOLDING
/* Skip over the visibly drawn line of the folded segment */
if (openfile->current->folded)
continue;
#endif
is_text = !white_string(openfile->current->data);
seen_text = seen_text || is_text;
}
/* Step forward one line again if we passed text but this line is blank. */
if (seen_text && openfile->current->next != NULL &&
white_string(openfile->current->data))
openfile->current = openfile->current->next;
line_step = get_next_visible_line(openfile->current);
if (seen_text && line_step != NULL &&
white_string(openfile->current->data)) {
openfile->current = line_step;
line_step = get_next_visible_line(line_step);
}
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
@ -257,12 +267,19 @@ void to_prev_block(void)
void to_next_block(void)
{
linestruct *was_current = openfile->current;
linestruct *line_step = get_next_visible_line(openfile->current);
bool is_white = white_string(openfile->current->data);
bool seen_white = is_white;
/* Skip forward until first nonblank line after some blank line(s). */
while (openfile->current->next != NULL && (!seen_white || is_white)) {
openfile->current = openfile->current->next;
while (line_step != NULL && (!seen_white || is_white)) {
openfile->current = line_step;
line_step = get_next_visible_line(line_step);
#ifdef ENABLE_FOLDING
/* Skip over the visibly drawn line of the folded segment */
if (openfile->current->folded)
continue;
#endif
is_white = white_string(openfile->current->data);
seen_white = seen_white || is_white;
}
@ -659,7 +676,7 @@ void do_left(void)
openfile->current_x);
#endif
} else if (openfile->current != openfile->filetop) {
openfile->current = openfile->current->prev;
openfile->current = get_prev_visible_line(openfile->current);
openfile->current_x = strlen(openfile->current->data);
}
@ -671,6 +688,13 @@ void do_right(void)
{
linestruct *was_current = openfile->current;
#ifdef ENABLE_FOLDING
if (openfile->current->folded) {
openfile->current = get_next_visible_line(openfile->current);
if (openfile->current == NULL)
openfile->current = was_current;
} else
#endif
if (openfile->current->data[openfile->current_x] != '\0') {
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
@ -681,7 +705,7 @@ void do_right(void)
openfile->current_x);
#endif
} else if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current = get_next_visible_line(openfile->current);
openfile->current_x = 0;
}

View File

@ -811,10 +811,19 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
line = 1;
#ifdef ENABLE_COLOR
#ifdef ENABLE_FOLDING
linestruct *edit_bottom = openfile->edittop;
for (int i = 0; edit_bottom != openfile->filebot && i < editwinrows; ++i)
edit_bottom = get_next_visible_line(edit_bottom);
if (line > edit_bottom->lineno ||
(ISSET(SOFTWRAP) && line > openfile->current->lineno))
recook |= perturbed;
#else
if (line > openfile->edittop->lineno + editwinrows ||
(ISSET(SOFTWRAP) && line > openfile->current->lineno))
recook |= perturbed;
#endif
#endif /* ENABLE_FOLDING */
#endif /* ENABLE_COLOR */
/* Iterate to the requested line. */
for (openfile->current = openfile->filetop; line > 1 &&

View File

@ -2980,8 +2980,13 @@ int update_softwrapped_line(linestruct *line)
/* Find out on which screen row the target line should be shown. */
while (someline != line && someline != NULL) {
row += 1 + extra_chunks_in(someline);
someline = someline->next;
#ifdef ENABLE_FOLDING
if (someline->folded)
++row;
else
#endif
row += 1 + extra_chunks_in(someline);
someline = get_next_visible_line(someline);
}
/* If the first chunk is offscreen, don't even try to display it. */
@ -3055,7 +3060,7 @@ int go_back_chunks(int nrows, linestruct **line, size_t *leftedge)
break;
i -= chunk;
*line = (*line)->prev;
*line = get_prev_visible_line(*line);
*leftedge = HIGHEST_POSITIVE;
}
@ -3063,8 +3068,13 @@ int go_back_chunks(int nrows, linestruct **line, size_t *leftedge)
*leftedge = leftedge_for(*leftedge, *line);
} else
#endif
for (i = nrows; i > 0 && (*line)->prev != NULL; i--)
*line = (*line)->prev;
{
linestruct *prev = get_prev_visible_line(*line);
for (i = nrows; i > 0 && prev != NULL; i--) {
*line = prev;
prev = get_prev_visible_line(prev);
}
}
return i;
}
@ -3105,8 +3115,13 @@ int go_forward_chunks(int nrows, linestruct **line, size_t *leftedge)
*leftedge = current_leftedge;
} else
#endif
for (i = nrows; i > 0 && (*line)->next != NULL; i--)
*line = (*line)->next;
{
linestruct *next = get_next_visible_line(*line);
for (i = nrows; i > 0 && next != NULL; i--) {
*line = next;
next = get_next_visible_line(*line);
}
}
return i;
}
@ -3133,20 +3148,47 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge)
/* Draw a scroll bar on the righthand side of the screen. */
void draw_scrollbar(void)
{
int fromline = openfile->edittop->lineno - 1;
int totallines = openfile->filebot->lineno;
int coveredlines = editwinrows;
int fromline = openfile->edittop->lineno - 1;
int coveredlines = 0;
linestruct *line = openfile->edittop;
if (ISSET(SOFTWRAP)) {
linestruct *line = openfile->edittop;
int extras = extra_chunks_in(line) - chunk_for(openfile->firstcolumn, line);
while (line->lineno + extras < fromline + editwinrows && line->next) {
line = line->next;
extras += extra_chunks_in(line);
int i = 0;
#ifdef ENABLE_FOLDING
if (line->folded)
coveredlines += get_folded_segment_length(line);
else
#endif
{
i = extra_chunks_in(line) - chunk_for(openfile->firstcolumn, line);
coveredlines = i;
}
coveredlines = line->lineno - fromline;
for (; i < editwinrows && line->next != NULL; ++i) {
line = get_next_visible_line(line);
#ifdef ENABLE_FOLDING
if (line->folded)
coveredlines += get_folded_segment_length(line);
else
#endif
{
i += extra_chunks_in(line);
++coveredlines;
}
}
} else {
#ifdef ENABLE_FOLDING
for (int i = 0; i < editwinrows && line->next != NULL; ++i) {
if (line->folded)
coveredlines += get_folded_segment_length(line);
else
++coveredlines;
line = get_next_visible_line(line);
}
#else
coveredlines = editwinrows;
#endif /* ENABLE_FOLDING */
}
int lowest = (fromline * editwinrows) / totallines;
@ -3214,7 +3256,7 @@ void edit_scroll(bool direction)
while (nrows > 0 && line != NULL) {
nrows -= update_line(line, (line == openfile->current) ?
openfile->current_x : 0);
line = line->next;
line = get_next_visible_line(line);
}
}
@ -3444,8 +3486,11 @@ void edit_redraw(linestruct *old_current, update_type manner)
while (line != openfile->current) {
update_line(line, 0);
line = (line->lineno > openfile->current->lineno) ?
line->prev : line->next;
if (line->lineno > openfile->current->lineno) {
line = get_prev_visible_line(line);
} else {
line = get_next_visible_line(line);
}
}
} else
#endif