From 1793a8cd8b68645963e780326e24490d4e918dd3 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Sat, 1 Apr 2023 14:16:09 -0700 Subject: [PATCH 4/7] 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 --- src/move.c | 42 ++++++++++++++++++++------ src/search.c | 11 ++++++- src/winio.c | 83 ++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 107 insertions(+), 29 deletions(-) diff --git a/src/move.c b/src/move.c index c2356be5..e7022630 100644 --- a/src/move.c +++ b/src/move.c @@ -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; } diff --git a/src/search.c b/src/search.c index 274b63e5..3ac86a1f 100644 --- a/src/search.c +++ b/src/search.c @@ -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 && diff --git a/src/winio.c b/src/winio.c index 3235a866..249c1096 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2979,8 +2979,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. */ @@ -3054,7 +3059,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; } @@ -3062,8 +3067,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; } @@ -3104,8 +3114,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; } @@ -3132,20 +3147,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; @@ -3213,7 +3255,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); } } @@ -3443,8 +3485,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 -- 2.39.2