From 3304675affd22e9ede2c92b5c0085961a797485e Mon Sep 17 00:00:00 2001 From: bptato Date: Thu, 18 Feb 2021 19:18:06 +0100 Subject: Support kitty image protocol --- etc.c | 4 ++++ fm.h | 1 + image.c | 4 ++++ rc.c | 1 + terms.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/etc.c b/etc.c index 2870caf..bc72005 100644 --- a/etc.c +++ b/etc.c @@ -2016,6 +2016,10 @@ base64_encode(const unsigned char *src, size_t len) unsigned long j; size_t k; + + if (!len) + return NULL; + k = len; if (k % 3) k += 3 - (k % 3); diff --git a/fm.h b/fm.h index c4a951f..997574a 100644 --- a/fm.h +++ b/fm.h @@ -316,6 +316,7 @@ extern int REV_LB[]; #define INLINE_IMG_OSC5379 1 #define INLINE_IMG_SIXEL 2 #define INLINE_IMG_ITERM2 3 +#define INLINE_IMG_KITTY 4 /* * Types. diff --git a/image.c b/image.c index 6e4e9b4..f25c895 100644 --- a/image.c +++ b/image.c @@ -198,6 +198,8 @@ syncImage(void) void put_image_osc5379(char *url, int x, int y, int w, int h, int sx, int sy, int sw, int sh); void put_image_sixel(char *url, int x, int y, int w, int h, int sx, int sy, int sw, int sh, int n_terminal_image); void put_image_iterm2(char *url, int x, int y, int w, int h); +void put_image_kitty(char *url, int x, int y, int w, int h, int sx, int sy, int + sw, int sh, int c, int r); void drawImage() @@ -256,6 +258,8 @@ drawImage() put_image_osc5379(url, x, y, w, h, sx, sy, sw, sh); } else if (enable_inline_image == INLINE_IMG_ITERM2) { put_image_iterm2(url, x, y, sw, sh); + } else if (enable_inline_image == INLINE_IMG_KITTY) { + put_image_kitty(url, x, y, w, h, i->sx, i->sy, sw * pixel_per_char, sh * pixel_per_line_i, sw, sh); } continue ; diff --git a/rc.c b/rc.c index 3c72ffb..18693a5 100644 --- a/rc.c +++ b/rc.c @@ -374,6 +374,7 @@ static struct sel_c inlineimgstr[] = { {N_S(INLINE_IMG_OSC5379), N_("OSC 5379 (mlterm)")}, {N_S(INLINE_IMG_SIXEL), N_("sixel (img2sixel)")}, {N_S(INLINE_IMG_ITERM2), N_("OSC 1337 (iTerm2)")}, + {N_S(INLINE_IMG_KITTY), N_("kitty (PNG only)")}, {0, NULL, NULL} }; #endif /* USE_IMAGE */ diff --git a/terms.c b/terms.c index f7c300e..45c5f86 100644 --- a/terms.c +++ b/terms.c @@ -521,7 +521,6 @@ put_image_iterm2(char *url, int x, int y, int w, int h) i = 0; while ((c = fgetc(fp)) != EOF) { cbuf[i] = c; - Strcat_char(buf, c); ++i; if (i == 3072) { base64 = base64_encode(cbuf, i); @@ -547,6 +546,85 @@ put_image_iterm2(char *url, int x, int y, int w, int h) MOVE(Currentbuf->cursorY,Currentbuf->cursorX); } +void +put_image_kitty(char *url, int x, int y, int w, int h, int sx, int sy, int sw, + int sh, int cols, int rows) +{ + Str buf; + char *base64, *cbuf, *type; + FILE *fp; + int c, i, j, k, t; + struct stat st; + + if (stat(url, &st)) + return; + + fp = fopen(url, "r"); + if (!fp) + return; + + type = guessContentType(url); + if(!strcasecmp(type, "image/png")) { + t = 100; + } else { + /* TODO: kitty +kitten icat or link imlib/gdkpixbuf? */ + return; + } + + MOVE(y, x); + buf = Sprintf("\x1b_Gf=100,s=%d,v=%d,a=T,m=1,X=%d,Y=%d,x=%d,y=%d," + "w=%d,h=%d,c=%d,r=%d;", + w, h, x, y, sx, sy, sw, sh, cols, rows); + + writestr(buf->ptr); + + cbuf = GC_MALLOC_ATOMIC(3072); + i = 0; + j = buf->length; + + while (buf->length + i / 3 * 4 < 4096 && (c = fgetc(fp)) != EOF) { + cbuf[i] = c; + ++i; + } + + base64 = base64_encode(cbuf, i); + if (!base64) + return; + + buf = Sprintf("%s\x1b\\", base64); + writestr(buf->ptr); + i = 0; + base64 = NULL; + + while ((c = fgetc(fp)) != EOF) { + if (!i && base64) { + buf = Sprintf("\x1b_Gm=1;%s\x1b\\", base64); + writestr(buf->ptr); + } + cbuf[i] = c; + ++i; + if (i == 3072) { + base64 = base64_encode(cbuf, i); + if (!base64) + return; + + i = 0; + } + } + + if (i) { + base64 = base64_encode(cbuf, i); + if (!base64) + return; + } + + if (base64) { + buf = Sprintf("\x1b_Gm=0;%s\x1b\\", base64); + writestr(buf->ptr); + } + MOVE(Currentbuf->cursorY, Currentbuf->cursorX); +} + static void save_gif(const char *path, u_char *header, size_t header_size, u_char *body, size_t body_size) { -- cgit v1.2.3