mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
sixel: fix cursor positioning logic
This adjusts the logic that positions the text cursor after emitting a sixel, when sixel scrolling mode is *enabled*. We’ve always mimicked XTerm’s behavior. However, XTerm recently changed its behavior, to better match that of an VT382. Now, the cursor is placed *on* the last row of the sixel, instead of on a new row after the sixel. This allows applications to print sixels to the bottom row of the terminal, without causing the content to scroll. Finally, there was a bug in the horizontal positioning of the cursor; it was placed on the *first* column of the row, instead of on the first column of the sixel.
This commit is contained in:
parent
8a3620bafa
commit
66d9b8da60
2 changed files with 26 additions and 20 deletions
|
|
@ -65,6 +65,15 @@
|
|||
* Opaque sixels now retain the background opacity (when current
|
||||
background color is the **default** background color)
|
||||
([#1360][1360]).
|
||||
* Text cursor’s vertical position after emitting a sixel, when sixel
|
||||
scrolling is **enabled** (the default) has been updated to match
|
||||
XTerm’s, and the VT382’s behavior: the cursor is positioned **on**
|
||||
the last sixel row, rather than _after_ it. This allows printing
|
||||
sixels on the last row without scrolling up, but also means
|
||||
applications may have to explicitly emit a newline to ensure the
|
||||
sixel is visible. For example, `cat`:ing a sixel in the shell will
|
||||
typically result in the last row not being visible, unless a newline
|
||||
is explicitly added.
|
||||
|
||||
[1371]: https://codeberg.org/dnkl/foot/pulls/1371
|
||||
[1360]: https://codeberg.org/dnkl/foot/issues/1360
|
||||
|
|
|
|||
37
sixel.c
37
sixel.c
|
|
@ -1043,6 +1043,23 @@ sixel_unhook(struct terminal *term)
|
|||
pixel_rows_left -= height;
|
||||
rows_avail -= image.rows;
|
||||
|
||||
if (do_scroll) {
|
||||
/* Yes, truncate last row. This matches XTerm’s, and VT382’s behavior */
|
||||
const int linefeed_count = image.height / term->cell_height;
|
||||
for (size_t i = 0; i < linefeed_count; i++)
|
||||
term_linefeed(term);
|
||||
|
||||
/* Position text cursor if this is the last image chunk */
|
||||
if (rows_avail == 0) {
|
||||
term_cursor_to(
|
||||
term,
|
||||
term->grid->cursor.point.row,
|
||||
(term->sixel.cursor_right_of_graphics
|
||||
? min(image.pos.col + image.cols, term->cols - 1)
|
||||
: image.pos.col));
|
||||
}
|
||||
}
|
||||
|
||||
/* Dirty touched cells, and scroll terminal content if necessary */
|
||||
for (size_t i = 0; i < image.rows; i++) {
|
||||
struct row *row = term->grid->rows[cur_row + i];
|
||||
|
|
@ -1055,26 +1072,6 @@ sixel_unhook(struct terminal *term)
|
|||
row->cells[col].attrs.clean = 0;
|
||||
}
|
||||
|
||||
if (do_scroll) {
|
||||
/*
|
||||
* Linefeed, *unless* we're on the very last row of
|
||||
* the final image (not just this chunk) and private
|
||||
* mode 8452 (leave cursor at the right of graphics)
|
||||
* is enabled.
|
||||
*/
|
||||
if (term->sixel.cursor_right_of_graphics &&
|
||||
rows_avail == 0 &&
|
||||
i >= image.rows - 1)
|
||||
{
|
||||
term_cursor_to(
|
||||
term,
|
||||
term->grid->cursor.point.row,
|
||||
min(image.pos.col + image.cols, term->cols - 1));
|
||||
} else {
|
||||
term_linefeed(term);
|
||||
term_carriage_return(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_sixel_overwrite_by_rectangle(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue