Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved inline image protocol support #161

Merged
merged 7 commits into from
Feb 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions etc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 5 additions & 1 deletion file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions fm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
82 changes: 47 additions & 35 deletions image.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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 ;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 0 additions & 48 deletions mimehead.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
15 changes: 14 additions & 1 deletion rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
33 changes: 32 additions & 1 deletion terms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;
Expand All @@ -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)
{
Expand Down