diff --git a/input.c b/input.c index b8d2f102..5adfdd8f 100644 --- a/input.c +++ b/input.c @@ -2151,10 +2151,13 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - u_char *buf = ictx->input_buf, *pbuf = ictx->param_buf; - size_t len = ictx->input_len, plen = ictx->param_len; + struct window_pane *wp = ictx->wp; + struct window *w = wp->window; + u_char *buf = ictx->input_buf; + size_t len = ictx->input_len; const char prefix[] = "tmux;"; const u_int prefixlen = (sizeof prefix) - 1; + struct sixel_image *si; if (ictx->flags & INPUT_DISCARD) return (0); @@ -2166,10 +2169,12 @@ input_dcs_dispatch(struct input_ctx *ictx) screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen); if (buf[0] == 'q') { - screen_write_rawsixel(sctx, (char *)"\033P", 2, 1); - screen_write_rawsixel(sctx, pbuf, plen, 1); - screen_write_rawsixel(sctx, buf, len, 1); - screen_write_rawsixel(sctx, (char *)"\033\\", 2, 0); + si = sixel_parse(buf, len, w->xpixel, w->ypixel); + if (si != NULL) { + sixel_log(si); + screen_write_sixelimage(sctx, si); + sixel_free(si); + } } return (0); diff --git a/screen-write.c b/screen-write.c index 9bd28836..5047bb72 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1672,17 +1672,14 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) tty_write(tty_cmd_rawstring, &ttyctx); } -/* Write unmodified SIXEL data. */ +/* Write a SIXEL image. */ void -screen_write_rawsixel(struct screen_write_ctx *ctx, u_char *str, u_int len, - int more) +screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si) { struct tty_ctx ttyctx; screen_write_initctx(ctx, &ttyctx); - ttyctx.ptr = str; - ttyctx.num = len; - ttyctx.more = more; + ttyctx.ptr = si; - tty_write(tty_cmd_rawsixel, &ttyctx); + tty_write(tty_cmd_sixelimage, &ttyctx); } diff --git a/sixel.c b/sixel.c index 76ecf48a..1246ec43 100644 --- a/sixel.c +++ b/sixel.c @@ -428,7 +428,7 @@ sixel_print_repeat(char **buf, size_t *len, size_t *used, u_int count, char ch) } char * -sixel_print(struct sixel_image *si, struct sixel_image *map) +sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size) { char *buf, tmp[64], *contains, data, last; size_t len, used = 0, tmplen; @@ -509,7 +509,10 @@ sixel_print(struct sixel_image *si, struct sixel_image *map) used--; sixel_print_add(&buf, &len, &used, "\033\\", 2); + buf[used] = '\0'; + if (size != NULL) + *size = used; free(contains); return (buf); diff --git a/tmux.h b/tmux.h index a5a60214..4b6cefd5 100644 --- a/tmux.h +++ b/tmux.h @@ -55,6 +55,7 @@ struct options; struct options_entry; struct options_array_item; struct session; +struct sixel_image; struct tmuxpeer; struct tmuxproc; struct winlink; @@ -1250,7 +1251,6 @@ struct tty_ctx { u_int num; void *ptr; - int more; /* * Cursor and region position before the screen was updated - this is @@ -1974,7 +1974,7 @@ void tty_cmd_scrolldown(struct tty *, const struct tty_ctx *); void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *); void tty_cmd_setselection(struct tty *, const struct tty_ctx *); void tty_cmd_rawstring(struct tty *, const struct tty_ctx *); -void tty_cmd_rawsixel(struct tty *, const struct tty_ctx *); +void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *); /* tty-term.c */ extern struct tty_terms tty_terms; @@ -2361,7 +2361,7 @@ void screen_write_collect_add(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); -void screen_write_rawsixel(struct screen_write_ctx *, u_char *, u_int, int); +void screen_write_sixelimage(struct screen_write_ctx *, struct sixel_image *); /* screen-redraw.c */ void screen_redraw_screen(struct client *); @@ -2711,6 +2711,7 @@ void sixel_log(struct sixel_image *); void sixel_size_in_cells(struct sixel_image *, u_int *, u_int *); struct sixel_image *sixel_scale(struct sixel_image *, u_int, u_int, u_int, u_int, u_int, u_int); -char *sixel_print(struct sixel_image *, struct sixel_image *); +char *sixel_print(struct sixel_image *, struct sixel_image *, + size_t *); #endif /* TMUX_H */ diff --git a/tty.c b/tty.c index cae2fd24..6cb04e2f 100644 --- a/tty.c +++ b/tty.c @@ -1867,15 +1867,45 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) } void -tty_cmd_rawsixel(struct tty *tty, const struct tty_ctx *ctx) +tty_cmd_sixelimage(struct tty *tty, const struct tty_ctx *ctx) { - int flags = (tty->term->flags|tty->term_flags); + struct window_pane *wp = ctx->wp; + struct screen *s = wp->screen; + struct sixel_image *si = ctx->ptr; + struct sixel_image *new; + int flags = (tty->term->flags|tty->term_flags); + char *data; + size_t size; + u_int cx = s->cx, cy = s->cy, sx, sy; + u_int i, j, x, y, rx, ry; - if ((flags & TERM_SIXEL) || tty_term_has(tty->term, TTYC_SXL)) { - tty_add(tty, ctx->ptr, ctx->num); - if (!ctx->more) - tty_invalidate(tty); + if ((~flags & TERM_SIXEL) && tty_term_has(tty->term, TTYC_SXL)) + return; + if (tty->xpixel == 0 || tty->ypixel == 0) + return; + + sixel_size_in_cells(si, &sx, &sy); + if (sx > wp->sx - cx) + sx = wp->sx - cx; + if (sy > wp->sy - cy) + sy = wp->sy - cy; + if (!tty_clamp_area(tty, ctx, cx, cy, sx, sy, &i, &j, &x, &y, &rx, &ry)) + return; + + new = sixel_scale(si, tty->xpixel, tty->ypixel, i, j, rx, ry); + if (new == NULL) + return; + + data = sixel_print(new, si, &size); + if (data != NULL) { + log_debug("%s: %zu bytes: %s", __func__, size, data); + tty_cursor(tty, x, y); + + tty_add(tty, data, size); + tty_invalidate(tty); + free(data); } + sixel_free(new); } static void