X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=789e79585bfd5837e867db038777d9b3493d3639;hb=8751809aff596fc2030026713651c11b3743f88e;hp=2788746e3b859882db2964208a127789715534f4;hpb=21f765426c36991edd8b14f4989d66187e9ff597;p=st.git diff --git a/st.c b/st.c index 2788746..789e795 100644 --- a/st.c +++ b/st.c @@ -183,8 +183,8 @@ typedef XftColor Color; typedef struct { long u; /* character code */ ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ + ushort fg; /* foreground */ + ushort bg; /* background */ } Glyph; typedef Glyph *Line; @@ -383,20 +383,20 @@ static void tmoveato(int, int); static void tnew(int, int); static void tnewline(int); static void tputtab(int); -static void tputc(char *, int); +static void tputc(long); static void treset(void); static void tresize(int, int); static void tscrollup(int, int); static void tscrolldown(int, int); static void tsetattr(int *, int); -static void tsetchar(char *, Glyph *, int, int); +static void tsetchar(long, Glyph *, int, int); static void tsetscroll(int, int); static void tswapscreen(void); static void tsetdirt(int, int); static void tsetdirtattr(int); static void tsetmode(bool, bool, int *, int); static void tfulldirt(void); -static void techo(char *, int); +static void techo(long); static void tcontrolcode(uchar ); static void tdectest(char ); static int32_t tdefcolor(int *, int *, int); @@ -453,7 +453,7 @@ static inline bool selected(int, int); static char *getsel(void); static void selcopy(Time); static void selscroll(int, int); -static void selsnap(int, int *, int *, int); +static void selsnap(int *, int *, int); static int x2col(int); static int y2row(int); static void getbuttoninfo(XEvent *); @@ -695,8 +695,8 @@ selnormalize(void) { sel.nb.y = MIN(sel.ob.y, sel.oe.y); sel.ne.y = MAX(sel.ob.y, sel.oe.y); - selsnap(sel.snap, &sel.nb.x, &sel.nb.y, -1); - selsnap(sel.snap, &sel.ne.x, &sel.ne.y, +1); + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); /* expand selection over line breaks */ if (sel.type == SEL_RECTANGULAR) @@ -720,12 +720,12 @@ selected(int x, int y) { } void -selsnap(int mode, int *x, int *y, int direction) { +selsnap(int *x, int *y, int direction) { int newx, newy, xt, yt; bool delim, prevdelim; Glyph *gp, *prevgp; - switch(mode) { + switch(sel.snap) { case SNAP_WORD: /* * Snap around if the word wraps around at the end or @@ -772,15 +772,15 @@ selsnap(int mode, int *x, int *y, int direction) { * previous line will be selected. */ *x = (direction < 0) ? 0 : term.col - 1; - if(direction < 0 && *y > 0) { + if(direction < 0) { for(; *y > 0; *y += direction) { if(!(term.line[*y-1][term.col-1].mode & ATTR_WRAP)) { break; } } - } else if(direction > 0 && *y < term.row-1) { - for(; *y < term.row; *y += direction) { + } else if(direction > 0) { + for(; *y < term.row-1; *y += direction) { if(!(term.line[*y][term.col-1].mode & ATTR_WRAP)) { break; @@ -855,12 +855,11 @@ mousereport(XEvent *e) { } if(!IS_SET(MODE_MOUSEX10)) { - button += (state & ShiftMask ? 4 : 0) - + (state & Mod4Mask ? 8 : 0) - + (state & ControlMask ? 16 : 0); + button += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); } - len = 0; if(IS_SET(MODE_MOUSESGR)) { len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x+1, y+1, @@ -1239,10 +1238,14 @@ execsh(void) { void sigchld(int a) { int stat, ret; + pid_t p; - if(waitpid(pid, &stat, 0) < 0) + if((p = waitpid(pid, &stat, WNOHANG)) < 0) die("Waiting for pid %hd failed: %s\n", pid, strerror(errno)); + if(pid != p) + return; + ret = WIFEXITED(stat) ? WEXITSTATUS(stat) : EXIT_FAILURE; if (ret != EXIT_SUCCESS) die("child finished with error '%d'\n", stat); @@ -1332,7 +1335,6 @@ ttyread(void) { static char buf[BUFSIZ]; static int buflen = 0; char *ptr; - char s[UTF_SIZ]; int charsize; /* size of utf8 char in bytes */ long unicodep; int ret; @@ -1345,8 +1347,7 @@ ttyread(void) { buflen += ret; ptr = buf; while((charsize = utf8decode(ptr, &unicodep, buflen))) { - utf8encode(unicodep, s); - tputc(s, charsize); + tputc(unicodep); ptr += charsize; buflen -= charsize; } @@ -1363,9 +1364,16 @@ ttywrite(const char *s, size_t n) { void ttysend(char *s, size_t n) { + int len; + long u; + ttywrite(s, n); if(IS_SET(MODE_ECHO)) - techo(s, n); + while((len = utf8decode(s, &u, n)) > 0) { + techo(u); + n -= len; + s += len; + } } void @@ -1614,7 +1622,7 @@ tmoveto(int x, int y) { } void -tsetchar(char *c, Glyph *attr, int x, int y) { +tsetchar(long u, Glyph *attr, int x, int y) { static char *vt100_0[62] = { /* 0x41 - 0x7e */ "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ @@ -1629,11 +1637,9 @@ tsetchar(char *c, Glyph *attr, int x, int y) { /* * The table is proudly stolen from rxvt. */ - if(term.trantbl[term.charset] == CS_GRAPHIC0) { - if(BETWEEN(c[0], 0x41, 0x7e) && vt100_0[c[0] - 0x41]) { - c = vt100_0[c[0] - 0x41]; - } - } + if(term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); if(term.line[y][x].mode & ATTR_WIDE) { if(x+1 < term.col) { @@ -1647,7 +1653,7 @@ tsetchar(char *c, Glyph *attr, int x, int y) { term.dirty[y] = 1; term.line[y][x] = *attr; - utf8decode(c, &term.line[y][x].u, UTF_SIZ); + term.line[y][x].u = u; } void @@ -1741,7 +1747,7 @@ tdefcolor(int *attr, int *npar, int l) { b = attr[*npar + 4]; *npar += 4; if(!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%d,%d,%d)\n", + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", r, g, b); else idx = TRUECOLOR(r, g, b); @@ -2431,26 +2437,18 @@ tputtab(int n) { } void -techo(char *buf, int len) { - for(; len > 0; buf++, len--) { - char c = *buf; - - if(ISCONTROL((uchar) c)) { /* control code */ - if(c & 0x80) { - c &= 0x7f; - tputc("^", 1); - tputc("[", 1); - } else if(c != '\n' && c != '\r' && c != '\t') { - c ^= 0x40; - tputc("^", 1); - } - tputc(&c, 1); - } else { - break; +techo(long u) { + if(ISCONTROL(u)) { /* control code */ + if(u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if(u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); } } - if(len) - tputc(buf, len); + tputc(u); } void @@ -2468,13 +2466,12 @@ tdeftran(char ascii) { void tdectest(char c) { - static char E[UTF_SIZ] = "E"; int x, y; if(c == '8') { /* DEC screen alignment test. */ for(x = 0; x < term.col; ++x) { for(y = 0; y < term.row; ++y) - tsetchar(E, &term.c.attr, x, y); + tsetchar('E', &term.c.attr, x, y); } } } @@ -2502,8 +2499,6 @@ tstrsequence(uchar c) { void tcontrolcode(uchar ascii) { - static char question[UTF_SIZ] = "?"; - switch(ascii) { case '\t': /* HT */ tputtab(1); @@ -2541,7 +2536,7 @@ tcontrolcode(uchar ascii) { term.charset = 1 - (ascii - '\016'); return; case '\032': /* SUB */ - tsetchar(question, &term.c.attr, term.c.x, term.c.y); + tsetchar('?', &term.c.attr, term.c.x, term.c.y); case '\030': /* CAN */ csireset(); break; @@ -2665,28 +2660,21 @@ eschandle(uchar ascii) { } void -tputc(char *c, int len) { - uchar ascii; +tputc(long u) { + char c[UTF_SIZ]; bool control; - long unicodep; - int width; + int width, len; Glyph *gp; - if(len == 1) { + len = utf8encode(u, c); + if((width = wcwidth(u)) == -1) { + memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ width = 1; - unicodep = ascii = *c; - } else { - utf8decode(c, &unicodep, UTF_SIZ); - if ((width = wcwidth(unicodep)) == -1) { - c = "\357\277\275"; /* UTF_INVALID */ - width = 1; - } - ascii = unicodep; } if(IS_SET(MODE_PRINT)) tprinter(c, len); - control = ISCONTROL(unicodep); + control = ISCONTROL(u); /* * STR sequence must be checked before anything else @@ -2695,10 +2683,8 @@ tputc(char *c, int len) { * character. */ if(term.esc & ESC_STR) { - if(len == 1 && - (ascii == '\a' || ascii == 030 || - ascii == 032 || ascii == 033 || - ISCONTROLC1(unicodep))) { + if(u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { term.esc &= ~(ESC_START|ESC_STR); term.esc |= ESC_STR_END; } else if(strescseq.len + len < sizeof(strescseq.buf) - 1) { @@ -2729,15 +2715,15 @@ tputc(char *c, int len) { * they must not cause conflicts with sequences. */ if(control) { - tcontrolcode(ascii); + tcontrolcode(u); /* * control codes are not shown ever */ return; } else if(term.esc & ESC_START) { if(term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = ascii; - if(BETWEEN(ascii, 0x40, 0x7E) + csiescseq.buf[csiescseq.len++] = u; + if(BETWEEN(u, 0x40, 0x7E) || csiescseq.len >= \ sizeof(csiescseq.buf)-1) { term.esc = 0; @@ -2746,11 +2732,11 @@ tputc(char *c, int len) { } return; } else if(term.esc & ESC_ALTCHARSET) { - tdeftran(ascii); + tdeftran(u); } else if(term.esc & ESC_TEST) { - tdectest(ascii); + tdectest(u); } else { - if (!eschandle(ascii)) + if (!eschandle(u)) return; /* sequence already finished */ } @@ -2779,7 +2765,7 @@ tputc(char *c, int len) { gp = &term.line[term.c.y][term.c.x]; } - tsetchar(c, &term.c.attr, term.c.x, term.c.y); + tsetchar(u, &term.c.attr, term.c.x, term.c.y); if(width == 2) { gp->mode |= ATTR_WIDE;