sixel: implement private mode 80 - sixel scrolling

When enabled (the default), sixels behave much like normal output; the
start where the cursor is, and the cursor moves with the
sixel. I.e. after emitting a sixel the cursor is left after the image;
either to the right, if private mode 8452 is enabled, or otherwise on
the next line. Terminal content is scrolled up if the sixel is larger
than the screen.

When disabled, sixels *always* start at (0,0), the cursor never moves,
and the terminal content never scrolls.

In other words, the ‘disabled’ mode is a much simpler mode.

All we need to do to support both modes is re-write the sixel-emitting
loop to:

* break early if we’re “out of rows”, i.e. we’ve reached the bottom of
  the screen.
* not linefeed, or move the cursor when scrolling is disabled

This patch also fixes a bug in the (new) implementation of private
mode 8452.

When emitting a sixel, we may break it up into smaller pieces, to
ensure a single sixel (as tracked internally) does not cross the
scrollback wrap-around.

The code that checked if we should do a linefeed or not, would skip
the linefeed on the last row of *each* such sixel piece. The correct
thing to do is to skip it only on the last row of the *last* piece.

I chose not to fix this bug in a separate patch since doing so would
have meant re-writing it again when implementing private mode 80.
This commit is contained in:
Daniel Eklöf 2021-02-26 09:28:03 +01:00
parent 792202bf29
commit 849427bf10
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 75 additions and 41 deletions

View file

@ -1178,6 +1178,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
.upper_fd = delay_upper_fd,
},
.sixel = {
.scrolling = true,
.use_private_palette = true,
.palette_size = SIXEL_MAX_COLORS,
.max_width = SIXEL_MAX_WIDTH,