]> Sergey Matveev's repositories - st.git/blobdiff - st.c
bump version to 0.9
[st.git] / st.c
diff --git a/st.c b/st.c
index abbbe4b86c44bbe29660e1a2beaea022b145a992..62def59f17cbf1bfd841210453ba29e5578d5610 100644 (file)
--- a/st.c
+++ b/st.c
@@ -161,6 +161,7 @@ static void csidump(void);
 static void csihandle(void);
 static void csiparse(void);
 static void csireset(void);
+static void osc_color_response(int, int, int);
 static int eschandle(uchar);
 static void strdump(void);
 static void strhandle(void);
@@ -186,18 +187,18 @@ static void tputc(Rune);
 static void treset(void);
 static void tscrollup(int, int);
 static void tscrolldown(int, int);
-static void tsetattr(int *, int);
-static void tsetchar(Rune, Glyph *, int, int);
+static void tsetattr(const int *, int);
+static void tsetchar(Rune, const Glyph *, int, int);
 static void tsetdirt(int, int);
 static void tsetscroll(int, int);
 static void tswapscreen(void);
-static void tsetmode(int, int, int *, int);
+static void tsetmode(int, int, const int *, int);
 static int twrite(const char *, int, int);
 static void tfulldirt(void);
 static void tcontrolcode(uchar );
 static void tdectest(char );
 static void tdefutf8(char);
-static int32_t tdefcolor(int *, int *, int);
+static int32_t tdefcolor(const int *, int *, int);
 static void tdeftran(char);
 static void tstrsequence(uchar);
 
@@ -226,10 +227,10 @@ static int iofd = 1;
 static int cmdfd;
 static pid_t pid;
 
-static uchar utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0};
-static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
-static Rune utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
-static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
+static const uchar utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0};
+static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
+static const Rune utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
+static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
 
 ssize_t
 xwrite(int fd, const char *s, size_t len)
@@ -269,12 +270,14 @@ xrealloc(void *p, size_t len)
 }
 
 char *
-xstrdup(char *s)
+xstrdup(const char *s)
 {
-       if ((s = strdup(s)) == NULL)
+       char *p;
+
+       if ((p = strdup(s)) == NULL)
                die("strdup: %s\n", strerror(errno));
 
-       return s;
+       return p;
 }
 
 size_t
@@ -347,25 +350,10 @@ utf8validate(Rune *u, size_t i)
        return i;
 }
 
-static const char base64_digits[] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
-       63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
-       2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-       22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 char
 base64dec_getc(const char **src)
 {
-       while (**src && !isprint(**src))
+       while (**src && !isprint((unsigned char)**src))
                (*src)++;
        return **src ? *((*src)++) : '=';  /* emulate padding if string ends */
 }
@@ -375,6 +363,13 @@ base64dec(const char *src)
 {
        size_t in_len = strlen(src);
        char *result, *dst;
+       static const char base64_digits[256] = {
+               [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+               0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+               13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
+               0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+       };
 
        if (in_len % 4)
                in_len += 4 - (in_len % 4);
@@ -518,7 +513,7 @@ selsnap(int *x, int *y, int direction)
 {
        int newx, newy, xt, yt;
        int delim, prevdelim;
-       Glyph *gp, *prevgp;
+       const Glyph *gp, *prevgp;
 
        switch (sel.snap) {
        case SNAP_WORD:
@@ -591,7 +586,7 @@ getsel(void)
 {
        char *str, *ptr;
        int y, bufsize, lastx, linelen;
-       Glyph *gp, *last;
+       const Glyph *gp, *last;
 
        if (sel.ob.x == -1)
                return NULL;
@@ -758,7 +753,7 @@ stty(char **args)
 }
 
 int
-ttynew(char *line, char *cmd, char *out, char **args)
+ttynew(const char *line, char *cmd, const char *out, char **args)
 {
        int m, s;
 
@@ -791,14 +786,15 @@ ttynew(char *line, char *cmd, char *out, char **args)
                break;
        case 0:
                close(iofd);
+               close(m);
                setsid(); /* create a new process group */
                dup2(s, 0);
                dup2(s, 1);
                dup2(s, 2);
                if (ioctl(s, TIOCSCTTY, NULL) < 0)
                        die("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
-               close(s);
-               close(m);
+               if (s > 2)
+                       close(s);
 #ifdef __OpenBSD__
                if (pledge("stdio getpw proc exec", NULL) == -1)
                        die("pledge\n");
@@ -943,7 +939,7 @@ ttyresize(int tw, int th)
 }
 
 void
-ttyhangup()
+ttyhangup(void)
 {
        /* Send SIGHUP to shell */
        kill(pid, SIGHUP);
@@ -1186,9 +1182,9 @@ tmoveto(int x, int y)
 }
 
 void
-tsetchar(Rune u, Glyph *attr, int x, int y)
+tsetchar(Rune u, const Glyph *attr, int x, int y)
 {
-       static char *vt100_0[62] = { /* 0x41 - 0x7e */
+       static const char *vt100_0[62] = { /* 0x41 - 0x7e */
                "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
                0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
                0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
@@ -1300,7 +1296,7 @@ tdeleteline(int n)
 }
 
 int32_t
-tdefcolor(int *attr, int *npar, int l)
+tdefcolor(const int *attr, int *npar, int l)
 {
        int32_t idx = -1;
        uint r, g, b;
@@ -1350,7 +1346,7 @@ tdefcolor(int *attr, int *npar, int l)
 }
 
 void
-tsetattr(int *attr, int l)
+tsetattr(const int *attr, int l)
 {
        int i;
        int32_t idx;
@@ -1468,9 +1464,9 @@ tsetscroll(int t, int b)
 }
 
 void
-tsetmode(int priv, int set, int *args, int narg)
+tsetmode(int priv, int set, const int *args, int narg)
 {
-       int alt, *lim;
+       int alt; const int *lim;
 
        for (lim = args + narg; args < lim; ++args) {
                if (priv) {
@@ -1839,11 +1835,41 @@ csireset(void)
        memset(&csiescseq, 0, sizeof(csiescseq));
 }
 
+void
+osc_color_response(int num, int index, int is_osc4)
+{
+       int n;
+       char buf[32];
+       unsigned char r, g, b;
+
+       if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
+               fprintf(stderr, "erresc: failed to fetch %s color %d\n",
+                       is_osc4 ? "osc4" : "osc",
+                       is_osc4 ? num : index);
+               return;
+       }
+
+       n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
+                    is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
+       if (n < 0 || n >= sizeof(buf)) {
+               fprintf(stderr, "error: %s while printing %s response\n",
+                       n < 0 ? "snprintf failed" : "truncation occurred",
+                       is_osc4 ? "osc4" : "osc");
+       } else {
+               ttywrite(buf, n, 1);
+       }
+}
+
 void
 strhandle(void)
 {
        char *p = NULL, *dec;
        int j, narg, par;
+       const struct { int idx; char *str; } osc_table[] = {
+               { defaultfg, "foreground" },
+               { defaultbg, "background" },
+               { defaultcs, "cursor" }
+       };
 
        term.esc &= ~(ESC_STR_END|ESC_STR);
        strparse();
@@ -1877,14 +1903,35 @@ strhandle(void)
                                }
                        }
                        return;
+               case 10:
+               case 11:
+               case 12:
+                       if (narg < 2)
+                               break;
+                       p = strescseq.args[1];
+                       if ((j = par - 10) < 0 || j >= LEN(osc_table))
+                               break; /* shouldn't be possible */
+
+                       if (!strcmp(p, "?")) {
+                               osc_color_response(par, osc_table[j].idx, 0);
+                       } else if (xsetcolorname(osc_table[j].idx, p)) {
+                               fprintf(stderr, "erresc: invalid %s color: %s\n",
+                                       osc_table[j].str, p);
+                       } else {
+                               tfulldirt();
+                       }
+                       return;
                case 4: /* color set */
                        if (narg < 3)
                                break;
                        p = strescseq.args[2];
                        /* FALLTHROUGH */
-               case 104: /* color reset, here p = NULL */
+               case 104: /* color reset */
                        j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
-                       if (xsetcolorname(j, p)) {
+
+                       if (p && !strcmp(p, "?")) {
+                               osc_color_response(j, 0, 1);
+                       } else if (xsetcolorname(j, p)) {
                                if (par == 104 && narg <= 1)
                                        return; /* color reset without parameter */
                                fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
@@ -1894,7 +1941,7 @@ strhandle(void)
                                 * TODO if defaultbg color is changed, borders
                                 * are dirty
                                 */
-                               redraw();
+                               tfulldirt();
                        }
                        return;
                }
@@ -2020,7 +2067,7 @@ void
 tdumpline(int n)
 {
        char buf[UTF_SIZ];
-       Glyph *bp, *end;
+       const Glyph *bp, *end;
 
        bp = &term.line[n][0];
        end = &bp[MIN(tlinelen(n), term.col) - 1];
@@ -2426,6 +2473,10 @@ check_control_code:
        if (width == 2) {
                gp->mode |= ATTR_WIDE;
                if (term.c.x+1 < term.col) {
+                       if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) {
+                               gp[2].u = ' ';
+                               gp[2].mode &= ~ATTR_WDUMMY;
+                       }
                        gp[1].u = '\0';
                        gp[1].mode = ATTR_WDUMMY;
                }