Skip to content

Instantly share code, notes, and snippets.

@saitoha
Created July 14, 2015 16:21
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save saitoha/ad59c1c4be095accaf4e to your computer and use it in GitHub Desktop.
Save saitoha/ad59c1c4be095accaf4e to your computer and use it in GitHub Desktop.
tmux: SIXEL integration (for mlterm / RLogin, not works on XTerm)
diff --git a/input.c b/input.c
index d1ff17f..33fad13 100644
--- a/input.c
+++ b/input.c
@@ -1805,6 +1805,7 @@ input_dcs_dispatch(struct input_ctx *ictx)
{
const char prefix[] = "tmux;";
const u_int prefix_len = (sizeof prefix) - 1;
+ u_char *p;
if (ictx->flags & INPUT_DISCARD)
return (0);
@@ -1818,6 +1819,15 @@ input_dcs_dispatch(struct input_ctx *ictx)
ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
}
+ for (p = ictx->input_buf; p != ictx->input_buf + ictx->input_len; p++) {
+ if ((*p >= 0 && *p <= 9) || *p == ';')
+ continue;
+ if (*p != 'q')
+ break;
+ screen_write_sixel(&ictx->ctx,
+ ictx->input_buf, ictx->input_len);
+ }
+
return (0);
}
diff --git a/screen-write.c b/screen-write.c
index e38c9f5..7a756c7 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1096,6 +1096,18 @@ screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
}
void
+screen_write_sixel(struct screen_write_ctx *ctx, u_char *str, u_int len)
+{
+ struct tty_ctx ttyctx;
+
+ screen_write_initctx(ctx, &ttyctx, 0);
+ ttyctx.ptr = str;
+ ttyctx.num = len;
+
+ tty_write(tty_cmd_write_sixel, &ttyctx);
+}
+
+void
screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
{
struct tty_ctx ttyctx;
diff --git a/tmux.h b/tmux.h
index f0fef0d..6363f35 100644
--- a/tmux.h
+++ b/tmux.h
@@ -368,6 +368,7 @@ enum tty_code_code {
TTYC_KUP5,
TTYC_KUP6,
TTYC_KUP7,
+ TTYC_MGC, /* clear_margins, MC */
TTYC_MS, /* modify xterm(1) selection */
TTYC_OP, /* orig_pair, op */
TTYC_REV, /* enter_reverse_mode, mr */
@@ -382,6 +383,7 @@ enum tty_code_code {
TTYC_SITM, /* enter_italics_mode, it */
TTYC_SMACS, /* enter_alt_charset_mode, as */
TTYC_SMCUP, /* enter_ca_mode, ti */
+ TTYC_SMGLR, /* set_lr_margin, ML */
TTYC_SMKX, /* keypad_xmit, ks */
TTYC_SMSO, /* enter_standout_mode, so */
TTYC_SMUL, /* enter_underline_mode, us */
@@ -1127,6 +1129,8 @@ struct tty {
u_int cx;
u_int cy;
+ u_int pixel_x;
+ u_int pixel_y;
u_int cstyle;
char *ccolour;
@@ -1641,6 +1645,7 @@ void tty_cmd_linefeed(struct tty *, const struct tty_ctx *);
void tty_cmd_utf8character(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_write_sixel(struct tty *, const struct tty_ctx *);
void tty_cmd_rawstring(struct tty *, const struct tty_ctx *);
void tty_bell(struct tty *);
@@ -2070,6 +2075,7 @@ void screen_write_clearscreen(struct screen_write_ctx *);
void screen_write_clearhistory(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_sixel(struct screen_write_ctx *, u_char *, u_int);
void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int);
/* screen-redraw.c */
diff --git a/tty-term.c b/tty-term.c
index d177c19..13cd982 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -215,6 +215,7 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_KUP5, TTYCODE_STRING, "kUP5" },
{ TTYC_KUP6, TTYCODE_STRING, "kUP6" },
{ TTYC_KUP7, TTYCODE_STRING, "kUP7" },
+ { TTYC_MGC, TTYCODE_STRING, "mgc" },
{ TTYC_MS, TTYCODE_STRING, "Ms" },
{ TTYC_OP, TTYCODE_STRING, "op" },
{ TTYC_REV, TTYCODE_STRING, "rev" },
@@ -229,6 +230,7 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_SITM, TTYCODE_STRING, "sitm" },
{ TTYC_SMACS, TTYCODE_STRING, "smacs" },
{ TTYC_SMCUP, TTYCODE_STRING, "smcup" },
+ { TTYC_SMGLR, TTYCODE_STRING, "smglr" },
{ TTYC_SMKX, TTYCODE_STRING, "smkx" },
{ TTYC_SMSO, TTYCODE_STRING, "smso" },
{ TTYC_SMUL, TTYCODE_STRING, "smul" },
diff --git a/tty.c b/tty.c
index 63380c2..8176499 100644
--- a/tty.c
+++ b/tty.c
@@ -90,6 +90,8 @@ tty_resize(struct tty *tty)
struct winsize ws;
u_int sx, sy;
+ memset(&ws, 0, sizeof(ws));
+
if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
sx = ws.ws_col;
if (sx == 0)
@@ -97,6 +99,8 @@ tty_resize(struct tty *tty)
sy = ws.ws_row;
if (sy == 0)
sy = 24;
+ tty->pixel_x = ws.ws_xpixel;
+ tty->pixel_y = ws.ws_ypixel;
} else {
sx = 80;
sy = 24;
@@ -831,7 +835,11 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
+ struct screen *s = ctx->wp->screen;
+
+ if ((!tty_term_has(tty->term, TTYC_SMGLR) &&
+ !tty_pane_full_width(tty, ctx)) ||
+ tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_IL1)) {
tty_redraw_region(tty, ctx);
@@ -840,16 +848,25 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
tty_attributes(tty, &grid_default_cell, ctx->wp);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode2(tty, TTYC_SMGLR,
+ ctx->xoff, ctx->xoff + screen_size_x(s) - 1);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ctx->num);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode(tty, TTYC_MGC);
}
void
tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
+ struct screen *s = ctx->wp->screen;
+
+ if ((!tty_term_has(tty->term, TTYC_SMGLR) &&
+ !tty_pane_full_width(tty, ctx)) ||
+ tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_DL1)) {
tty_redraw_region(tty, ctx);
@@ -858,10 +875,15 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
tty_attributes(tty, &grid_default_cell, ctx->wp);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode2(tty, TTYC_SMGLR,
+ ctx->xoff, ctx->xoff + screen_size_x(s) - 1);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ctx->num);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode(tty, TTYC_MGC);
}
void
@@ -916,10 +938,14 @@ tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
{
+ struct screen *s = ctx->wp->screen;
+
if (ctx->ocy != ctx->orupper)
return;
- if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
+ if ((!tty_term_has(tty->term, TTYC_SMGLR) &&
+ !tty_pane_full_width(tty, ctx)) ||
+ tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_RI)) {
tty_redraw_region(tty, ctx);
@@ -928,21 +954,29 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
tty_attributes(tty, &grid_default_cell, ctx->wp);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode2(tty, TTYC_SMGLR,
+ ctx->xoff, ctx->xoff + screen_size_x(s) - 1);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper);
tty_putcode(tty, TTYC_RI);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode(tty, TTYC_MGC);
}
void
tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
+ struct screen *s = wp->screen;
if (ctx->ocy != ctx->orlower)
return;
- if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, wp) ||
+ if ((!tty_term_has(tty->term, TTYC_SMGLR) &&
+ !tty_pane_full_width(tty, ctx)) ||
+ tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR)) {
if (tty_large_region(tty, ctx))
wp->flags |= PANE_REDRAW;
@@ -961,10 +995,15 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
tty_attributes(tty, &grid_default_cell, wp);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode2(tty, TTYC_SMGLR,
+ ctx->xoff, ctx->xoff + screen_size_x(s) - 1);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
tty_putc(tty, '\n');
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode(tty, TTYC_MGC);
}
void
@@ -1145,6 +1184,38 @@ tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx)
}
void
+tty_cmd_write_sixel(struct tty *tty, const struct tty_ctx *ctx)
+{
+ u_char *str = ctx->ptr;
+ u_char *start = str;
+ u_char *end = str + ctx->num;
+ u_char *p = str;
+ int pixel_y = 6;
+ struct screen *s = ctx->wp->screen;
+
+ if (s != NULL && tty->pixel_y > 0) {
+ tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode2(tty, TTYC_SMGLR, ctx->xoff,
+ ctx->xoff + screen_size_x(s) - 1);
+ tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
+ bufferevent_write(tty->event, "\033P", 2);
+ bufferevent_write(tty->event, str, ctx->num);
+ bufferevent_write(tty->event, "\033\\", 2);
+ if (!tty_pane_full_width(tty, ctx))
+ tty_putcode(tty, TTYC_MGC);
+ tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
+ tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
+ for (p = start; p != end; ++p)
+ if (*p == '-')
+ pixel_y += 6;
+ s->cy += (pixel_y - 1) * tty->sy / tty->pixel_y + 1;
+ if (s->cy > screen_size_y(s) - 1)
+ s->cy = screen_size_y(s) - 1;
+ }
+}
+
+void
tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
{
u_int i;
set -ga terminal-overrides ',xterm*:smglr=\E7\E[?69h\E[%i%p1%d;%p2%ds\E8:mgc=\E7\E[?69l\E8'
@HalosGhost
Copy link

Unfortunately, it looks like this patch does not work for me using tmux under yaft. I receive no errors; rather, img2sixel simply produces nothing, as if I were on a terminal that does not provide sixel-support.

A valiant effort though it is! However, given the tmux devs' unwillingness to add support to mainline, I'm exploring some other options as replacements and namely have my eyes on dvtm/abduco.

@saitoha
Copy link
Author

saitoha commented Jul 15, 2015

@HalosGhost It reproduced for me.
The reason is that the master branch of yaft does not return terminal pixel size over TIOCGWINSZ.
yaft develop branch seemes to do it.
uobikiemukot/yaft@9bb83c1#diff-8c689842501e39ed6229d6ec73103c42R121
You should use the develop branch or apply it.
https://gist.github.com/saitoha/2c662697f972170150ab

Even if you do above solution, it won't works with tmux's vertical split feature, because yaft does not supports DECLRMM/DECSLRM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment