diff options
Diffstat (limited to 'st.c')
-rw-r--r-- | st.c | 464 |
1 files changed, 170 insertions, 294 deletions
@@ -14,7 +14,6 @@ #include <sys/types.h> #include <sys/wait.h> #include <termios.h> -#include <time.h> #include <unistd.h> #include <wchar.h> @@ -36,23 +35,13 @@ #define ESC_ARG_SIZ 16 #define STR_BUF_SIZ ESC_BUF_SIZ #define STR_ARG_SIZ ESC_ARG_SIZ -#define HISTSIZE 2000 /* macros */ #define IS_SET(flag) ((term.mode & (flag)) != 0) -#define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ - term.scr + HISTSIZE + 1) % HISTSIZE] : \ - term.line[(y) - term.scr]) - -#define TLINE_HIST(y) ((y) <= HISTSIZE-term.row+2 ? term.hist[(y)] : term.line[(y-HISTSIZE+term.row-3)]) - -/* constants */ -#define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: </dev/null" enum term_mode { MODE_WRAP = 1 << 0, @@ -62,7 +51,6 @@ enum term_mode { MODE_ECHO = 1 << 4, MODE_PRINT = 1 << 5, MODE_UTF8 = 1 << 6, - MODE_SIXEL = 1 << 7, }; enum cursor_movement { @@ -89,12 +77,11 @@ enum charset { enum escape_state { ESC_START = 1, ESC_CSI = 2, - ESC_STR = 4, /* OSC, PM, APC */ + ESC_STR = 4, /* DCS, OSC, PM, APC */ ESC_ALTCHARSET = 8, ESC_STR_END = 16, /* a final string was encountered */ ESC_TEST = 32, /* Enter in test mode */ ESC_UTF8 = 64, - ESC_DCS =128, }; typedef struct { @@ -128,9 +115,6 @@ typedef struct { int col; /* nb col */ Line *line; /* screen */ Line *alt; /* alternate screen */ - Line hist[HISTSIZE]; /* history buffer */ - int histi; /* history index */ - int scr; /* scroll back */ int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ @@ -143,14 +127,14 @@ typedef struct { int charset; /* current charset */ int icharset; /* selected charset for sequence */ int *tabs; - struct timespec last_ximspot_update; + Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; /* CSI Escape sequence structs */ /* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */ typedef struct { char buf[ESC_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + size_t len; /* raw string length */ char priv; int arg[ESC_ARG_SIZ]; int narg; /* nb of args */ @@ -161,8 +145,9 @@ typedef struct { /* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ typedef struct { char type; /* ESC type ... */ - char buf[STR_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ char *args[STR_ARG_SIZ]; int narg; /* nb of args */ } STREscape; @@ -199,8 +184,8 @@ static void tnewline(int); static void tputtab(int); static void tputc(Rune); static void treset(void); -static void tscrollup(int, int, int); -static void tscrolldown(int, int, int); +static void tscrollup(int, int); +static void tscrolldown(int, int); static void tsetattr(int *, int); static void tsetchar(Rune, Glyph *, int, int); static void tsetdirt(int, int); @@ -380,8 +365,9 @@ static const char base64_digits[] = { char base64dec_getc(const char **src) { - while (**src && !isprint(**src)) (*src)++; - return *((*src)++); + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } char * @@ -399,6 +385,10 @@ base64dec(const char *src) int c = base64_digits[(unsigned char) base64dec_getc(&src)]; int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + *dst++ = (a << 2) | ((b & 0x30) >> 4); if (c == -1) break; @@ -424,24 +414,10 @@ tlinelen(int y) { int i = term.col; - if (TLINE(y)[i - 1].mode & ATTR_WRAP) + if (term.line[y][i - 1].mode & ATTR_WRAP) return i; - while (i > 0 && TLINE(y)[i - 1].u == ' ') - --i; - - return i; -} - -int -tlinehistlen(int y) -{ - int i = term.col; - - if (TLINE_HIST(y)[i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && TLINE_HIST(y)[i - 1].u == ' ') + while (i > 0 && term.line[y][i - 1].u == ' ') --i; return i; @@ -550,7 +526,7 @@ selsnap(int *x, int *y, int direction) * Snap around if the word wraps around at the end or * beginning of a line. */ - prevgp = &TLINE(*y)[*x]; + prevgp = &term.line[*y][*x]; prevdelim = ISDELIM(prevgp->u); for (;;) { newx = *x + direction; @@ -565,14 +541,14 @@ selsnap(int *x, int *y, int direction) yt = *y, xt = *x; else yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + if (!(term.line[yt][xt].mode & ATTR_WRAP)) break; } if (newx >= tlinelen(newy)) break; - gp = &TLINE(newy)[newx]; + gp = &term.line[newy][newx]; delim = ISDELIM(gp->u); if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || (delim && gp->u != prevgp->u))) @@ -593,14 +569,14 @@ selsnap(int *x, int *y, int direction) *x = (direction < 0) ? 0 : term.col - 1; if (direction < 0) { for (; *y > 0; *y += direction) { - if (!(TLINE(*y-1)[term.col-1].mode + if (!(term.line[*y-1][term.col-1].mode & ATTR_WRAP)) { break; } } } else if (direction > 0) { for (; *y < term.row-1; *y += direction) { - if (!(TLINE(*y)[term.col-1].mode + if (!(term.line[*y][term.col-1].mode & ATTR_WRAP)) { break; } @@ -631,13 +607,13 @@ getsel(void) } if (sel.type == SEL_RECTANGULAR) { - gp = &TLINE(y)[sel.nb.x]; + gp = &term.line[y][sel.nb.x]; lastx = sel.ne.x; } else { - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } - last = &TLINE(y)[MIN(lastx, linelen-1)]; + last = &term.line[y][MIN(lastx, linelen-1)]; while (last >= gp && last->u == ' ') --last; @@ -657,7 +633,8 @@ getsel(void) * st. * FIXME: Fix the computer world. */ - if ((y < sel.ne.y || lastx >= linelen) && !(last->mode & ATTR_WRAP)) + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) *ptr++ = '\n'; } *ptr = 0; @@ -688,7 +665,7 @@ die(const char *errstr, ...) void execsh(char *cmd, char **args) { - char *sh, *prog; + char *sh, *prog, *arg; const struct passwd *pw; errno = 0; @@ -702,13 +679,20 @@ execsh(char *cmd, char **args) if ((sh = getenv("SHELL")) == NULL) sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - if (args) + if (args) { prog = args[0]; - else if (utmp) + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { prog = utmp; - else + arg = NULL; + } else { prog = sh; - DEFAULT(args, ((char *[]) {prog, NULL})); + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); unsetenv("COLUMNS"); unsetenv("LINES"); @@ -746,7 +730,7 @@ sigchld(int a) die("child exited with status %d\n", WEXITSTATUS(stat)); else if (WIFSIGNALED(stat)) die("child terminated due to signal %d\n", WTERMSIG(stat)); - exit(0); + _exit(0); } void @@ -839,30 +823,31 @@ ttyread(void) { static char buf[BUFSIZ]; static int buflen = 0; - int written; - int ret; + int ret, written; /* append read bytes to unprocessed bytes */ - if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) - die("couldn't read from shell: %s\n", strerror(errno)); - buflen += ret; + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any uncomplete utf8 char for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - - return ret; + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } } void ttywrite(const char *s, size_t n, int may_echo) { const char *next; - Arg arg = (Arg) { .i = term.scr }; - - kscrolldown(&arg); if (may_echo && IS_SET(MODE_ECHO)) twrite(s, n, 1); @@ -1058,16 +1043,10 @@ void tnew(int col, int row) { term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; - clock_gettime(CLOCK_MONOTONIC, &term.last_ximspot_update); tresize(col, row); treset(); } -int tisaltscr(void) -{ - return IS_SET(MODE_ALTSCREEN); -} - void tswapscreen(void) { @@ -1080,53 +1059,13 @@ tswapscreen(void) } void -kscrolldown(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (n > term.scr) - n = term.scr; - - if (term.scr > 0) { - term.scr -= n; - selscroll(0, -n); - tfulldirt(); - } -} - -void -kscrollup(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (term.scr <= HISTSIZE-n) { - term.scr += n; - selscroll(0, n); - tfulldirt(); - } -} - -void -tscrolldown(int orig, int n, int copyhist) +tscrolldown(int orig, int n) { int i; Line temp; LIMIT(n, 0, term.bot-orig+1); - if (copyhist) { - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[term.bot]; - term.line[term.bot] = temp; - } - tsetdirt(orig, term.bot-n); tclearregion(0, term.bot-n+1, term.col-1, term.bot); @@ -1140,23 +1079,13 @@ tscrolldown(int orig, int n, int copyhist) } void -tscrollup(int orig, int n, int copyhist) +tscrollup(int orig, int n) { int i; Line temp; LIMIT(n, 0, term.bot-orig+1); - if (copyhist) { - term.histi = (term.histi + 1) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[orig]; - term.line[orig] = temp; - } - - if (term.scr > 0 && term.scr < HISTSIZE) - term.scr = MIN(term.scr + n, HISTSIZE-1); - tclearregion(0, orig, term.col-1, orig+n-1); tsetdirt(orig+n, term.bot); @@ -1175,27 +1104,17 @@ selscroll(int orig, int n) if (sel.ob.x == -1) return; - if (BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) { - if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) { + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { selclear(); - return; - } - if (sel.type == SEL_RECTANGULAR) { - if (sel.ob.y < term.top) - sel.ob.y = term.top; - if (sel.oe.y > term.bot) - sel.oe.y = term.bot; } else { - if (sel.ob.y < term.top) { - sel.ob.y = term.top; - sel.ob.x = 0; - } - if (sel.oe.y > term.bot) { - sel.oe.y = term.bot; - sel.oe.x = term.col; - } + selnormalize(); } - selnormalize(); } } @@ -1205,7 +1124,7 @@ tnewline(int first_col) int y = term.c.y; if (y == term.bot) { - tscrollup(term.top, 1, 1); + tscrollup(term.top, 1); } else { y++; } @@ -1373,14 +1292,14 @@ void tinsertblankline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n, 0); + tscrolldown(term.c.y, n); } void tdeleteline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n, 0); + tscrollup(term.c.y, n); } int32_t @@ -1730,6 +1649,12 @@ csihandle(void) if (csiescseq.arg[0] == 0) ttywrite(vtiden, strlen(vtiden), 0); break; + case 'b': /* REP -- if last char is printable print it <n> more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; case 'C': /* CUF -- Cursor <n> Forward */ case 'a': /* HPR -- Cursor <n> Forward */ DEFAULT(csiescseq.arg[0], 1); @@ -1811,11 +1736,11 @@ csihandle(void) break; case 'S': /* SU -- Scroll <n> line up */ DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0], 0); + tscrollup(term.top, csiescseq.arg[0]); break; case 'T': /* SD -- Scroll <n> line down */ DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0], 0); + tscrolldown(term.top, csiescseq.arg[0]); break; case 'L': /* IL -- Insert <n> blank lines */ DEFAULT(csiescseq.arg[0], 1); @@ -1853,7 +1778,7 @@ csihandle(void) break; case 'n': /* DSR – Device Status Report (cursor position) */ if (csiescseq.arg[0] == 6) { - len = snprintf(buf, sizeof(buf),"\033[%i;%iR", + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y+1, term.c.x+1); ttywrite(buf, len, 0); } @@ -1890,7 +1815,7 @@ csihandle(void) void csidump(void) { - int i; + size_t i; uint c; fprintf(stderr, "ESC["); @@ -1931,13 +1856,21 @@ strhandle(void) case ']': /* OSC -- Operating System Command */ switch (par) { case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; case 2: if (narg > 1) xsettitle(strescseq.args[1]); return; case 52: - if (narg > 2) { + if (narg > 2 && allowwindowops) { dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); @@ -1948,35 +1881,22 @@ strhandle(void) } return; case 4: /* color set */ - case 10: /* foreground set */ - case 11: /* background set */ - case 12: /* cursor color */ - if ((par == 4 && narg < 3) || narg < 2) + if (narg < 3) break; - p = strescseq.args[((par == 4) ? 2 : 1)]; + p = strescseq.args[2]; /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ - if (par == 10) - j = defaultfg; - else if (par == 11) - j = defaultbg; - else if (par == 12) - j = defaultcs; - else - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); + j, p ? p : "(null)"); } else { /* * TODO if defaultbg color is changed, borders * are dirty */ - if (j == defaultbg) - xclearwin(); redraw(); } return; @@ -1986,7 +1906,6 @@ strhandle(void) xsettitle(strescseq.args[0]); return; case 'P': /* DCS -- Device Control String */ - term.mode |= ESC_DCS; case '_': /* APC -- Application Program Command */ case '^': /* PM -- Privacy Message */ return; @@ -2019,56 +1938,6 @@ strparse(void) } void -strdump(void) -{ - int i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - memset(&strescseq, 0, sizeof(strescseq)); -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void externalpipe(const Arg *arg) { int to[2]; @@ -2099,19 +1968,16 @@ externalpipe(const Arg *arg) /* ignore sigpipe for now, in case child exists early */ oldsigpipe = signal(SIGPIPE, SIG_IGN); newline = 0; - /* modify externalpipe patch to pipe history too */ - for (n = 0; n <= HISTSIZE + 2; n++) { - bp = TLINE_HIST(n); - lastpos = MIN(tlinehistlen(n) +1, term.col) - 1; + for (n = 0; n < term.row; n++) { + bp = term.line[n]; + lastpos = MIN(tlinelen(n) + 1, term.col) - 1; if (lastpos < 0) break; - if (lastpos == 0) - continue; end = &bp[lastpos + 1]; for (; bp < end; ++bp) if (xwrite(to[1], buf, utf8encode(bp->u, buf)) < 0) break; - if ((newline = TLINE_HIST(n)[lastpos].mode & ATTR_WRAP)) + if ((newline = term.line[n][lastpos].mode & ATTR_WRAP)) continue; if (xwrite(to[1], "\n", 1) < 0) break; @@ -2125,25 +1991,56 @@ externalpipe(const Arg *arg) } void -iso14755(const Arg *arg) +strdump(void) { - FILE *p; - char *us, *e, codepoint[9], uc[UTF_SIZ]; - unsigned long utf32; + size_t i; + uint c; - if (!(p = popen(ISO14755CMD, "r"))) - return; + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} - us = fgets(codepoint, sizeof(codepoint), p); - pclose(p); +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} - if (!us || *us == '\0' || *us == '-' || strlen(us) > 7) - return; - if ((utf32 = strtoul(us, &e, 16)) == ULONG_MAX || - (*e != '\n' && *e != '\0')) - return; +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} - ttywrite(uc, utf8encode(utf32, uc), 1); +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } } void @@ -2184,7 +2081,7 @@ tdumpline(int n) bp = &term.line[n][0]; end = &bp[MIN(tlinelen(n), term.col) - 1]; if (bp != end || bp->u != ' ') { - for ( ;bp <= end; ++bp) + for ( ; bp <= end; ++bp) tprinter(buf, utf8encode(bp->u, buf)); } tprinter("\n", 1); @@ -2255,12 +2152,9 @@ tdectest(char c) void tstrsequence(uchar c) { - strreset(); - switch (c) { case 0x90: /* DCS -- Device Control String */ c = 'P'; - term.esc |= ESC_DCS; break; case 0x9f: /* APC -- Application Program Command */ c = '_'; @@ -2272,6 +2166,7 @@ tstrsequence(uchar c) c = ']'; break; } + strreset(); strescseq.type = c; term.esc |= ESC_STR; } @@ -2314,6 +2209,7 @@ tcontrolcode(uchar ascii) return; case '\032': /* SUB */ tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ case '\030': /* CAN */ csireset(); break; @@ -2409,7 +2305,7 @@ eschandle(uchar ascii) return 0; case 'D': /* IND -- Linefeed */ if (term.c.y == term.bot) { - tscrollup(term.top, 1, 1); + tscrollup(term.top, 1); } else { tmoveto(term.c.x, term.c.y+1); } @@ -2422,7 +2318,7 @@ eschandle(uchar ascii) break; case 'M': /* RI -- Reverse index */ if (term.c.y == term.top) { - tscrolldown(term.top, 1, 1); + tscrolldown(term.top, 1); } else { tmoveto(term.c.x, term.c.y-1); } @@ -2468,15 +2364,13 @@ tputc(Rune u) Glyph *gp; control = ISCONTROL(u); - if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { + if (u < 127 || !IS_SET(MODE_UTF8)) { c[0] = u; width = len = 1; } else { len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) { - memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ + if (!control && (width = wcwidth(u)) == -1) width = 1; - } } if (IS_SET(MODE_PRINT)) @@ -2491,24 +2385,12 @@ tputc(Rune u) if (term.esc & ESC_STR) { 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_START|ESC_STR); term.esc |= ESC_STR_END; goto check_control_code; } - if (IS_SET(MODE_SIXEL)) { - /* TODO: implement sixel mode */ - return; - } - if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') - term.mode |= MODE_SIXEL; - - if (strescseq.len+len >= sizeof(strescseq.buf)-1) { + if (strescseq.len+len >= strescseq.siz) { /* * Here is a bug in terminals. If the user never sends * some code to stop the str or esc command, then st @@ -2522,7 +2404,10 @@ tputc(Rune u) * term.esc = 0; * strhandle(); */ - return; + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); } memmove(&strescseq.buf[strescseq.len], c, len); @@ -2541,6 +2426,8 @@ check_control_code: /* * control codes are not shown ever */ + if (!term.esc) + term.lastc = 0; return; } else if (term.esc & ESC_START) { if (term.esc & ESC_CSI) { @@ -2571,7 +2458,7 @@ check_control_code: */ return; } - if (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y)) + if (selected(term.c.x, term.c.y)) selclear(); gp = &term.line[term.c.y][term.c.x]; @@ -2590,6 +2477,7 @@ check_control_code: } tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; if (width == 2) { gp->mode |= ATTR_WIDE; @@ -2613,7 +2501,7 @@ twrite(const char *buf, int buflen, int show_ctrl) int n; for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { + if (IS_SET(MODE_UTF8)) { /* process a complete utf8 char */ charsize = utf8decode(buf + n, &u, buflen - n); if (charsize == 0) @@ -2640,7 +2528,7 @@ twrite(const char *buf, int buflen, int show_ctrl) void tresize(int col, int row) { - int i, j; + int i; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); int *bp; @@ -2677,14 +2565,6 @@ tresize(int col, int row) term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - for (i = 0; i < HISTSIZE; i++) { - term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); - for (j = mincol; j < col; j++) { - term.hist[i][j] = term.c.attr; - term.hist[i][j].u = ' '; - } - } - /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); @@ -2737,19 +2617,20 @@ void drawregion(int x1, int y1, int x2, int y2) { int y; + for (y = y1; y < y2; y++) { if (!term.dirty[y]) continue; term.dirty[y] = 0; - xdrawline(TLINE(y), x1, y, x2); + xdrawline(term.line[y], x1, y, x2); } } void draw(void) { - int cx = term.c.x; + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; if (!xstartdraw()) return; @@ -2763,19 +2644,14 @@ draw(void) cx--; drawregion(0, 0, term.col, term.row); - if (term.scr == 0) - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], - term.ocx, term.ocy, term.line[term.ocy][term.ocx], - term.line[term.ocy], term.col); - term.ocx = cx, term.ocy = term.c.y; + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx], + term.line[term.ocy], term.col); + term.ocx = cx; + term.ocy = term.c.y; xfinishdraw(); - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - if (ximspot_update_interval && TIMEDIFF(now, term.last_ximspot_update) > ximspot_update_interval) { + if (ocx != term.ocx || ocy != term.ocy) xximspot(term.ocx, term.ocy); - term.last_ximspot_update = now; - } } void |