/* Internal representation of the screen */ typedef struct { int row; /* nb row */ int col; /* nb col */ Line *line; /* screen */ Line *alt; /* alternate screen */ int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ int ocy; /* old cursor row */ int top; /* top scroll limit */ int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ int esc; /* escape state flags */ char trantbl[4]; /* charset table translation */ int charset; /* current charset */ int icharset; /* selected charset for sequence */ int *tabs; Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; --- st.c +++ st.c @@ -105,26 +99,6 @@ typedef struct { int alt; } Selection; -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; -} Term; - /* CSI Escape sequence structs */ /* ESC '[' [[ [] [;]] []] */ typedef struct { @@ -1929,7 +1956,39 @@ strhandle(void) xsettitle(strescseq.args[0]); return; case 'P': /* DCS -- Device Control String */ - term.mode |= ESC_DCS; + if (IS_SET(MODE_SIXEL)) { + term.mode &= ~MODE_SIXEL; + new_image = malloc(sizeof(ImageList)); + memset(new_image, 0, sizeof(ImageList)); + new_image->x = term.c.x; + new_image->y = term.c.y; + new_image->width = sixel_st.image.width; + new_image->height = sixel_st.image.height; + new_image->pixels = malloc(new_image->width * new_image->height * 4); + if (sixel_parser_finalize(&sixel_st, new_image->pixels) != 0) { + perror("sixel_parser_finalize() failed"); + sixel_parser_deinit(&sixel_st); + return; + } + sixel_parser_deinit(&sixel_st); + if (term.images) { + ImageList *im; + for (im = term.images; im->next;) + im = im->next; + im->next = new_image; + new_image->prev = im; + } else { + term.images = new_image; + } + for (i = 0; i < (sixel_st.image.height + win.ch-1)/win.ch; ++i) { + int x; + tclearregion(term.c.x, term.c.y, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw, term.c.y); + for (x = term.c.x; x < MIN(term.col, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw); x++) + term.line[term.c.y][x].mode |= ATTR_SIXEL; + tnewline(1); + } + } + return; case '_': /* APC -- Application Program Command */ case '^': /* PM -- Privacy Message */ return; @@ -2358,21 +2418,17 @@ tputc(Rune u) if (u == '\a' || u == 030 || u == 032 || u == 033 || ISCONTROLC1(u)) { term.esc &= ~(ESC_START|ESC_STR|ESC_DCS); - if (IS_SET(MODE_SIXEL)) { - /* TODO: render sixel */; - term.mode &= ~MODE_SIXEL; - return; - } term.esc |= ESC_STR_END; goto check_control_code; } if (IS_SET(MODE_SIXEL)) { - /* TODO: implement sixel mode */ + if (sixel_parser_parse(&sixel_st, (unsigned char *)&u, 1) != 0) + perror("sixel_parser_parse() failed"); return; } - if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') - term.mode |= MODE_SIXEL; + if (term.esc & ESC_DCS) + goto check_control_code; if (strescseq.len+len >= sizeof(strescseq.buf)-1) { /*