diff options
author | Tatsuya Kinoshita <tats@debian.org> | 2021-02-06 04:07:40 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-06 04:07:40 +0000 |
commit | e66ca9fa4ee8eb9e9370bba0bfa4d2084a300a3e (patch) | |
tree | 759d7d3bd2023845ab491d0f1810c8f278c6b150 | |
parent | Update ChangeLog (diff) | |
parent | Clarify inline image setting's wording (diff) | |
download | w3m-e66ca9fa4ee8eb9e9370bba0bfa4d2084a300a3e.tar.gz w3m-e66ca9fa4ee8eb9e9370bba0bfa4d2084a300a3e.zip |
Merge pull request #161 from bptato/master
Improved inline image protocol support
-rw-r--r-- | etc.c | 60 | ||||
-rw-r--r-- | file.c | 6 | ||||
-rw-r--r-- | fm.h | 5 | ||||
-rw-r--r-- | image.c | 82 | ||||
-rw-r--r-- | main.c | 8 | ||||
-rw-r--r-- | mimehead.c | 48 | ||||
-rw-r--r-- | proto.h | 2 | ||||
-rw-r--r-- | rc.c | 15 | ||||
-rw-r--r-- | terms.c | 33 |
9 files changed, 169 insertions, 90 deletions
@@ -2004,3 +2004,63 @@ void (*mySignal(int signal_number, void (*action) (int))) (int) { return (signal(signal_number, action)); #endif } + +static char Base64Table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +char * +base64_encode(const unsigned char *src, size_t len) +{ + unsigned char *w, *at; + const unsigned char *in, *endw; + int j; + size_t k; + + k = len; + if (k % 3) + k += 3 - (k % 3); + k = k / 3 * 4; + + if (k + 1 < len) + return NULL; + + w = GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(k + 1); + 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 (char *)w; +} @@ -1175,7 +1175,11 @@ 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); + char *base64 = base64_encode(s->ptr, s->length); + if (!base64) + return Strnew_charp("Basic "); + else + return Strnew_m_charp("Basic ", base64, NULL); } #ifdef USE_DIGEST_AUTH @@ -312,6 +312,11 @@ extern int REV_LB[]; #define EOL(l) (&(l)->ptr[(l)->length]) #define IS_EOL(p,l) ((p)==&(l)->ptr[(l)->length]) +#define INLINE_IMG_NONE 0 +#define INLINE_IMG_OSC5379 1 +#define INLINE_IMG_SIXEL 2 +#define INLINE_IMG_ITERM2 3 + /* * Types. */ @@ -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,41 +215,48 @@ drawImage() i = &terminal_image[j]; if (enable_inline_image) { - #if 0 + /* + * So this shouldn't ever happen, but if it does then at least let's + * not have external programs fetch images from the Internet... + */ + if (!i->cache->touch || stat(i->cache->file,&st)) + return; + + char *url = i->cache->file; + + int x = i->x / pixel_per_char_i; + int y = i->y / pixel_per_line_i; + + int w = i->cache->a_width > 0 ? ( + (i->cache->width + i->x % pixel_per_char_i + pixel_per_char_i - 1) / + pixel_per_char_i) : 0; + int h = i->cache->a_height > 0 ? ( + (i->cache->height + i->y % pixel_per_line_i + pixel_per_line_i - 1) / + pixel_per_line_i) : 0; + + int sx = i->sx / pixel_per_char_i; + int sy = i->sy / pixel_per_line_i; + + int sw = (i->width + i->sx % pixel_per_char_i + pixel_per_char_i - 1) / + pixel_per_char_i; + 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", - ((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, + i->cache->file, + x, y, w, h, sx, sy, sw, sh, pixel_per_char_i, pixel_per_line_i); - #endif - (enable_inline_image == 2 ? put_image_sixel : put_image_osc5379)( - ((enable_inline_image == 2 /* sixel */ || getenv("WINDOWID")) && - /* XXX I don't know why but sometimes i->cache->file doesn't exist. */ - i->cache->touch && stat(i->cache->file,&st) == 0) ? - /* local */ i->cache->file : /* remote */ i->cache->url, - i->x / pixel_per_char_i, - i->y / pixel_per_line_i, - #if 1 - i->cache->a_width > 0 ? - (i->cache->width + i->x % pixel_per_char_i + pixel_per_char_i - 1) / - pixel_per_char_i : - #endif - 0, - - #if 1 - i->cache->a_height > 0 ? - (i->cache->height + i->y % pixel_per_line_i + pixel_per_line_i - 1) / - pixel_per_line_i : - #endif - 0, - i->sx / pixel_per_char_i, - i->sy / pixel_per_line_i, - (i->width + i->sx % pixel_per_char_i + pixel_per_char_i - 1) / pixel_per_char_i, - (i->height + i->sy % pixel_per_line_i + pixel_per_line_i - 1) / pixel_per_line_i, - n_terminal_image); +#endif + + + if (enable_inline_image == INLINE_IMG_SIXEL) { + put_image_sixel(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 ; } @@ -471,7 +479,9 @@ loadImage(Buffer *buf, int flag) */ cache->pid = 0; } + /*TODO make sure removing this didn't break anything unlink(cache->touch); + */ image_cache[i] = NULL; } @@ -544,8 +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 make sure removing this didn't break anything if (!b || !b->real_type || strncasecmp(b->real_type, "image/", 6)) unlink(cache->file); + */ #if defined(HAVE_SYMLINK) && defined(HAVE_LSTAT) symlink(cache->file, cache->touch); #else @@ -599,7 +611,7 @@ getImage(Image * image, ParsedURL *current, int flag) cache->pid = 0; cache->index = 0; cache->loaded = IMG_FLAG_UNLOADED; - if (enable_inline_image == 1) { + if (enable_inline_image == INLINE_IMG_OSC5379) { if (image->width > 0 && image->width % pixel_per_char_i > 0) image->width += (pixel_per_char_i - image->width % pixel_per_char_i); @@ -123,7 +123,7 @@ static int searchKeyNum(void); #define help() fusage(stdout, 0) #define usage() fusage(stderr, 1) -int enable_inline_image; /* 1 == mlterm OSC 5379, 2 == sixel */ +int enable_inline_image; static void fversion(FILE * f) @@ -692,10 +692,10 @@ main(int argc, char **argv, char **envp) } #endif else if (!strcmp("-ri", argv[i])) { - enable_inline_image = 1; + enable_inline_image = INLINE_IMG_OSC5379; } else if (!strcmp("-sixel", argv[i])) { - enable_inline_image = 2; + enable_inline_image = INLINE_IMG_SIXEL; } else if (!strcmp("-num", argv[i])) showLineNum = TRUE; @@ -5961,7 +5961,7 @@ deleteFiles() } while ((f = popText(fileToDelete)) != NULL) { unlink(f); - if (enable_inline_image == 2 && strcmp(f+strlen(f)-4, ".gif") == 0) { + if (enable_inline_image == INLINE_IMG_SIXEL && strcmp(f+strlen(f)-4, ".gif") == 0) { Str firstframe = Strnew_charp(f); Strcat_charp(firstframe, "-1"); unlink(firstframe->ptr); @@ -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; -} @@ -828,3 +828,5 @@ extern void dispVer(void); void srand48(long); long lrand48(void); #endif + +extern char *base64_encode(const unsigned char *src, size_t len); @@ -86,6 +86,7 @@ static int OptionEncode = FALSE; #define CMT_IMAGE_SCALE N_("Scale of image (%)") #define CMT_IMGDISPLAY N_("External command to display image") #define CMT_IMAGE_MAP_LIST N_("Use link list of image map") +#define CMT_INLINE_IMG_PROTOCOL N_("Inline image display method") #endif #define CMT_MULTICOL N_("Display file names in multi-column format") #define CMT_ALT_ENTITY N_("Use ASCII equivalents to display entities") @@ -363,6 +364,16 @@ static struct sel_c graphic_char_str[] = { {0, NULL, NULL} }; +#ifdef USE_IMAGE +static struct sel_c inlineimgstr[] = { + {N_S(INLINE_IMG_NONE), N_("external command")}, + {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 */ + struct param_ptr params1[] = { {"tabstop", P_NZINT, PI_TEXT, (void *)&Tabstop, CMT_TABSTOP, NULL}, {"indent_incr", P_NZINT, PI_TEXT, (void *)&IndentIncr, CMT_INDENT_INCR, @@ -424,6 +435,8 @@ struct param_ptr params1[] = { CMT_EXT_IMAGE_VIEWER, NULL}, {"image_scale", P_SCALE, PI_TEXT, (void *)&image_scale, CMT_IMAGE_SCALE, NULL}, + {"inline_img_protocol", P_INT, PI_SEL_C, (void *)&enable_inline_image, + CMT_INLINE_IMG_PROTOCOL, (void *)inlineimgstr}, {"imgdisplay", P_STRING, PI_TEXT, (void *)&Imgdisplay, CMT_IMGDISPLAY, NULL}, {"image_map_list", P_INT, PI_ONOFF, (void *)&image_map_list, @@ -1223,7 +1236,7 @@ sync_with_option(void) init_migemo(); #endif #ifdef USE_IMAGE - if (fmInitialized && displayImage) + if (fmInitialized && (displayImage || enable_inline_image)) initImage(); #else displayImage = FALSE; /* XXX */ @@ -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) { |