summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2019-11-28 13:21:40 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2019-11-28 13:21:40 +0000
commite01df67ca106e57f5c689e75f313f8cda6f8b805 (patch)
tree3e48885961d7919135b7a5461c62c5382867a6f6
parente24acc0b5c3ac19dcacebdea243dcc7784215ffa (diff)
Crop and scale images as needed when drawing them.
-rw-r--r--input.c17
-rw-r--r--screen-write.c11
-rw-r--r--sixel.c5
-rw-r--r--tmux.h9
-rw-r--r--tty.c42
5 files changed, 60 insertions, 24 deletions
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))
+ 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;
- if ((flags & TERM_SIXEL) || tty_term_has(tty->term, TTYC_SXL)) {
- tty_add(tty, ctx->ptr, ctx->num);
- if (!ctx->more)
- tty_invalidate(tty);
+ 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