grid: get rid of empty row at the bottom after reflowing

When the window is resized and we reflow the text, we ended up
inserting an empty row at the bottom.

This happens whenever the actual last row has a hard linebreak (which
almost always is the case); we then end the reflow with a line break,
causing an extra, empty, row to be allocated and inserted.

This patch fixes this by detecting when:

1) the last row is empty
2) the next to last row has a hard line break

In this case, we roll back the last line break, by adjusting the new
offset we just calculated, and free:ing the empty row.

TODO: it would be nice if we could detect this in the reflow loop
instead, and avoid doing the last line break all together. I haven’t
yet been able to find a way to do this correctly.

Closes #1108
This commit is contained in:
Daniel Eklöf 2022-08-05 18:26:37 +02:00
parent 129e1a9b8e
commit aaf5894ad9
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 22 additions and 0 deletions

View file

@ -109,6 +109,7 @@
* Poor performance when making very large selections ([#1114][1114]).
* Bogus error message when using systemd socket activation for server
mode ([#1107][1107])
* Empty line at the bottom after a window resize ([#1108][1108]).
[1055]: https://codeberg.org/dnkl/foot/issues/1055
[1092]: https://codeberg.org/dnkl/foot/issues/1092
@ -117,6 +118,7 @@
[1120]: https://codeberg.org/dnkl/foot/issues/1120
[1114]: https://codeberg.org/dnkl/foot/issues/1114
[1107]: https://codeberg.org/dnkl/foot/issues/1107
[1108]: https://codeberg.org/dnkl/foot/issues/1108
### Security

20
grid.c
View file

@ -984,6 +984,26 @@ grid_resize_and_reflow(
/* Set offset such that the last reflowed row is at the bottom */
grid->offset = new_row_idx - new_screen_rows + 1;
if (new_col_idx == 0) {
int next_to_last_new_row_idx = new_row_idx - 1;
next_to_last_new_row_idx += new_rows;
next_to_last_new_row_idx &= new_rows - 1;
const struct row *next_to_last_row = new_grid[next_to_last_new_row_idx];
if (next_to_last_row != NULL && next_to_last_row->linebreak) {
/*
* The next to last row is actually the *last* row. But we
* ended the reflow with a line-break, causing an empty
* row to be inserted at the bottom. Undo this.
*/
/* TODO: can we detect this in the reflow loop above instead? */
grid->offset--;
grid_row_free(new_grid[new_row_idx]);
new_grid[new_row_idx] = NULL;
}
}
while (grid->offset < 0)
grid->offset += new_rows;
while (new_grid[grid->offset] == NULL)