From e4570e8b6e17382e1cc4984684f861524d5b02f4 Mon Sep 17 00:00:00 2001 From: bptato Date: Tue, 2 Feb 2021 22:14:46 +0100 Subject: Support iTerm2 graphics protocol, replace encodeB with base64_encode --- etc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ file.c | 2 +- fm.h | 1 + image.c | 38 +++++++++++++++++--------------------- mimehead.c | 48 ------------------------------------------------ proto.h | 2 ++ rc.c | 1 + terms.c | 33 ++++++++++++++++++++++++++++++++- 8 files changed, 113 insertions(+), 71 deletions(-) diff --git a/etc.c b/etc.c index 801b098..aa8b61d 100644 --- a/etc.c +++ b/etc.c @@ -2004,3 +2004,62 @@ void (*mySignal(int signal_number, void (*action) (int))) (int) { return (signal(signal_number, action)); #endif } + +static char Base64Table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +const char * +base64_encode(const unsigned char *src, int len) +{ + unsigned char *w, *at; + const unsigned char *in, *endw; + int j, k; + + k = len; + if (k % 3) + k += 3 - (k % 3); + k = k / 3 * 4; + + if (k < len) + return ""; + + w = GC_MALLOC_ATOMIC(k); + w[k] = 0; + + at = w; + in = src; + + endw = src + len - 2; + + while (in < endw) { + j = *in++; + j = j << 8 | *in++; + j = j << 8 | *in++; + + *at++ = Base64Table[(j >> 18) & 0x3f]; + *at++ = Base64Table[(j >> 12) & 0x3f]; + *at++ = Base64Table[(j >> 6) & 0x3f]; + *at++ = Base64Table[j & 0x3f]; + } + + if (in - src - len) { + if (in - src - len == 1) { + j = *in++; + j = j << 8; + j = j << 8; + *at++ = Base64Table[(j >> 18) & 0x3f]; + *at++ = Base64Table[(j >> 12) & 0x3f]; + *at++ = '='; + *at++ = '='; + } else { + j = *in++; + j = j << 8 | *in++; + j = j << 8; + *at++ = Base64Table[(j >> 18) & 0x3f]; + *at++ = Base64Table[(j >> 12) & 0x3f]; + *at++ = Base64Table[(j >> 6) & 0x3f]; + *at++ = '='; + } + } + return w; +} diff --git a/file.c b/file.c index 1ab1c55..0e6a79a 100644 --- a/file.c +++ b/file.c @@ -1175,7 +1175,7 @@ AuthBasicCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu, Str s = Strdup(uname); Strcat_char(s, ':'); Strcat(s, pw); - return Strnew_m_charp("Basic ", encodeB(s->ptr)->ptr, NULL); + return Strnew_m_charp("Basic ", base64_encode(s->ptr, s->length), NULL); } #ifdef USE_DIGEST_AUTH diff --git a/fm.h b/fm.h index a80e5f9..216cd53 100644 --- a/fm.h +++ b/fm.h @@ -315,6 +315,7 @@ extern int REV_LB[]; #define INLINE_IMG_NONE 0 #define INLINE_IMG_OSC5379 1 #define INLINE_IMG_SIXEL 2 +#define INLINE_IMG_ITERM2 3 /* * Types. diff --git a/image.c b/image.c index 6fc79a6..6e4e9b4 100644 --- a/image.c +++ b/image.c @@ -195,8 +195,9 @@ syncImage(void) n_terminal_image = 0; } -void put_image_osc5379(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_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 drawImage() @@ -214,19 +215,6 @@ drawImage() i = &terminal_image[j]; if (enable_inline_image) { -#if 0 - if(stat(i->cache->file, &st)) { - fprintf(stderr,"file %s x %d y %d w %d h %d sx %d sy %d sw %d sh %d (ppc %d ppl %d)\n", - ((enable_inline_image == 2 || getenv("WINDOWID")) && - i->cache->touch) ? i->cache->file : i->cache->url, - i->x, i->y, - i->cache->width > 0 ? i->cache->width : 0, - i->cache->height > 0 ? i->cache->height : 0, - i->sx, i->sy, i->width, i->height, - pixel_per_char_i, pixel_per_line_i); - } -#endif - /* * So this shouldn't ever happen, but if it does then at least let's * not have external programs fetch images from the Internet... @@ -254,10 +242,20 @@ drawImage() int sh = (i->height + i->sy % pixel_per_line_i + pixel_per_line_i - 1) / pixel_per_line_i; +#if 0 + fprintf(stderr,"file %s x %d y %d w %d h %d sx %d sy %d sw %d sh %d (ppc %d ppl %d)\n", + i->cache->file, + x, y, w, h, sx, sy, sw, sh, + pixel_per_char_i, pixel_per_line_i); +#endif + + if (enable_inline_image == INLINE_IMG_SIXEL) { put_image_sixel(url, x, y, w, h, sx, sy, sw, sh, n_terminal_image); - } else { - put_image_osc5379(url, x, y, w, h, sx, sy, sw, sh, n_terminal_image); + } else if (enable_inline_image == INLINE_IMG_OSC5379) { + 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); } continue ; @@ -481,8 +479,7 @@ loadImage(Buffer *buf, int flag) */ cache->pid = 0; } - /*TODO I'm pretty sure this can be accessed again when the buffer isn't - * discarded. not sure though + /*TODO make sure removing this didn't break anything unlink(cache->touch); */ image_cache[i] = NULL; @@ -557,11 +554,10 @@ loadImage(Buffer *buf, int flag) setup_child(FALSE, 0, -1); image_source = cache->file; b = loadGeneralFile(cache->url, cache->current, NULL, 0, NULL); - /* TODO this apparently messes up stuff but why? */ -#if 0 + /* TODO make sure removing this didn't break anything if (!b || !b->real_type || strncasecmp(b->real_type, "image/", 6)) unlink(cache->file); -#endif + */ #if defined(HAVE_SYMLINK) && defined(HAVE_LSTAT) symlink(cache->file, cache->touch); #else diff --git a/mimehead.c b/mimehead.c index d16270c..2479137 100644 --- a/mimehead.c +++ b/mimehead.c @@ -350,51 +350,3 @@ decodeMIME0(Str orgstr) return cnv; } -/* encoding */ - -static char Base64Table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - -Str -encodeB(char *a) -{ - unsigned char d[3]; - unsigned char c1, c2, c3, c4; - int i, n_pad; - Str w = Strnew(); - - while (1) { - if (*a == '\0') - break; - n_pad = 0; - d[1] = d[2] = 0; - for (i = 0; i < 3; i++) { - d[i] = a[i]; - if (a[i] == '\0') { - n_pad = 3 - i; - break; - } - } - c1 = d[0] >> 2; - c2 = (((d[0] << 4) | (d[1] >> 4)) & 0x3f); - if (n_pad == 2) { - c3 = c4 = 64; - } - else if (n_pad == 1) { - c3 = ((d[1] << 2) & 0x3f); - c4 = 64; - } - else { - c3 = (((d[1] << 2) | (d[2] >> 6)) & 0x3f); - c4 = (d[2] & 0x3f); - } - Strcat_char(w, Base64Table[c1]); - Strcat_char(w, Base64Table[c2]); - Strcat_char(w, Base64Table[c3]); - Strcat_char(w, Base64Table[c4]); - if (n_pad) - break; - a += 3; - } - return w; -} diff --git a/proto.h b/proto.h index 0c6483d..1f8e7d2 100644 --- a/proto.h +++ b/proto.h @@ -828,3 +828,5 @@ extern void dispVer(void); void srand48(long); long lrand48(void); #endif + +extern const char *base64_encode(const unsigned char *src, int len); diff --git a/rc.c b/rc.c index d015d31..b9a849f 100644 --- a/rc.c +++ b/rc.c @@ -369,6 +369,7 @@ static struct sel_c inlineimgstr[] = { {N_S(INLINE_IMG_NONE), N_("none")}, {N_S(INLINE_IMG_OSC5379), N_("mlterm")}, {N_S(INLINE_IMG_SIXEL), N_("sixel")}, + {N_S(INLINE_IMG_ITERM2), N_("iterm2")}, {0, NULL, NULL} }; #endif /* USE_IMAGE */ diff --git a/terms.c b/terms.c index a636ac0..966006a 100644 --- a/terms.c +++ b/terms.c @@ -469,7 +469,7 @@ writestr(char *s) #ifdef USE_IMAGE void -put_image_osc5379(char *url, int x, int y, int w, int h, int sx, int sy, int sw, int sh, int n_terminal_image) +put_image_osc5379(char *url, int x, int y, int w, int h, int sx, int sy, int sw, int sh) { Str buf; char *size ; @@ -485,6 +485,37 @@ put_image_osc5379(char *url, int x, int y, int w, int h, int sx, int sy, int sw, MOVE(Currentbuf->cursorY,Currentbuf->cursorX); } + +void +put_image_iterm2(char *url, int x, int y, int w, int h) +{ + Str buf, filecontent; + const char *base64; + FILE *fp; + + fp = fopen(url, "r"); + if (!fp) + return; + filecontent = Strfgetall(fp); + + base64 = base64_encode(filecontent->ptr, filecontent->length); + if (!base64) + return; + + MOVE(y,x); + buf = Sprintf("\x1b]1337;" + "File=" + "name=%s;" + "size=%d;" + "width=%d;" + "height=%d;" + "preserveAspectRatio=0;" + "inline=1" + ":%s\a", url, filecontent->length, w, h, 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