painting: always do backtracking for the first row of the screen

Backtracking from the first row is needed in case a start match was
added recently somewhere offscreen and the user jumped to the current
location (instead of scrolling) so that the CWOULDBE markings did not
reach the current lines.

Also, search for an end match only for the first screen row.  For the
other rows, rely on the CENDAFTER, CWHOLELINE, and CWOULDBE values to
indicate whether there *is* an end match (the first two values) or not.
This saves considerable time when there is no end match in the large
remainder of a buffer: it will search in vain for the end match just
once, instead of for every row of the screen.

This fixes https://savannah.gnu.org/bugs/?59948,
and addresses https://savannah.gnu.org/bugs/?59945.

Bug existed since version 2.7.5, commit b3bcc8ee.
master
Benno Schulenberg 2021-01-27 12:18:42 +01:00
parent 1364b41dc9
commit 43d94692ce
1 changed files with 10 additions and 1 deletions

View File

@ -2557,7 +2557,7 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
/* First check the multidata of the preceding line -- it tells
* us about the situation so far, and thus what to do here. */
if (start_line != NULL && start_line->multidata != NULL) {
if (row > 0 && start_line != NULL && start_line->multidata != NULL) {
if (start_line->multidata[varnish->id] == CWHOLELINE ||
start_line->multidata[varnish->id] == CENDAFTER ||
start_line->multidata[varnish->id] == CWOULDBE)
@ -2621,9 +2621,12 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
/* We've already checked that there is no end between the start
* and the current line. But is there an end after the start
* at all? We don't paint unterminated starts. */
if (row == 0) {
while (end_line != NULL && regexec(varnish->end, end_line->data,
1, &endmatch, 0) == REG_NOMATCH)
end_line = end_line->next;
} else if (regexec(varnish->end, line->data, 1, &endmatch, 0) != 0)
end_line = line->next;
/* If there is no end, there is nothing to paint. */
if (end_line == NULL) {
@ -2631,6 +2634,12 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
continue;
}
if (end_line != line && line->prev == start_line && line->prev->multidata &&
line->prev->multidata[varnish->id] == CWOULDBE) {
line->multidata[varnish->id] = CWOULDBE;
continue;
}
/* If the end is on a later line, paint whole line, and be done. */
if (end_line != line) {
wattron(edit, varnish->attributes);