X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/5528280fae23968ffd3cf0527881cabddc24cf85..21f765426c36991edd8b14f4989d66187e9ff597:/st.c?ds=inline

diff --git a/st.c b/st.c
index c67619d..2788746 100644
--- a/st.c
+++ b/st.c
@@ -72,6 +72,7 @@ char *argv0;
 #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177')
 #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
 #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
+#define ISDELIM(u) (BETWEEN(u, 0, 127) && strchr(worddelimiters, u) != NULL)
 #define LIMIT(x, a, b)    (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
 #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg)
 #define IS_SET(flag) ((term.mode & (flag)) != 0)
@@ -158,8 +159,7 @@ enum escape_state {
 
 enum window_state {
 	WIN_VISIBLE = 1,
-	WIN_REDRAW  = 2,
-	WIN_FOCUSED = 4
+	WIN_FOCUSED = 2
 };
 
 enum selection_type {
@@ -181,7 +181,7 @@ typedef XftDraw *Draw;
 typedef XftColor Color;
 
 typedef struct {
-	char c[UTF_SIZ]; /* character code */
+	long u;           /* character code */
 	ushort mode;      /* attribute flags */
 	uint32_t fg;      /* foreground  */
 	uint32_t bg;      /* background  */
@@ -411,6 +411,7 @@ static void tstrsequence(uchar);
 
 static inline ushort sixd_to_16bit(int);
 static void xdraws(char *, Glyph, int, int, int, int);
+static void xdrawglyph(Glyph, int, int);
 static void xhints(void);
 static void xclear(int, int, int, int);
 static void xdrawcursor(void);
@@ -460,9 +461,8 @@ static void mousereport(XEvent *);
 
 static size_t utf8decode(char *, long *, size_t);
 static long utf8decodebyte(char, size_t *);
-static size_t utf8encode(long, char *, size_t);
+static size_t utf8encode(long, char *);
 static char utf8encodebyte(long, size_t);
-static size_t utf8len(char *);
 static size_t utf8validate(long *, size_t);
 
 static ssize_t xwrite(int, const char *, size_t);
@@ -611,11 +611,11 @@ utf8decodebyte(char c, size_t *i) {
 }
 
 size_t
-utf8encode(long u, char *c, size_t clen) {
+utf8encode(long u, char *c) {
 	size_t len, i;
 
 	len = utf8validate(&u, 0);
-	if(clen < len)
+	if(len > UTF_SIZ)
 		return 0;
 	for(i = len - 1; i != 0; --i) {
 		c[i] = utf8encodebyte(u, 0);
@@ -630,11 +630,6 @@ utf8encodebyte(long u, size_t i) {
 	return utfbyte[i] | (u & ~utfmask[i]);
 }
 
-size_t
-utf8len(char *c) {
-	return utf8decode(c, &(long){0}, UTF_SIZ);
-}
-
 size_t
 utf8validate(long *u, size_t i) {
 	if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
@@ -680,7 +675,7 @@ tlinelen(int y) {
 	if(term.line[y][i - 1].mode & ATTR_WRAP)
 		return i;
 
-	while(i > 0 && term.line[y][i - 1].c[0] == ' ')
+	while(i > 0 && term.line[y][i - 1].u == ' ')
 		--i;
 
 	return i;
@@ -737,7 +732,7 @@ selsnap(int mode, int *x, int *y, int direction) {
 		 * beginning of a line.
 		 */
 		prevgp = &term.line[*y][*x];
-		prevdelim = strchr(worddelimiters, prevgp->c[0]) != NULL;
+		prevdelim = ISDELIM(prevgp->u);
 		for(;;) {
 			newx = *x + direction;
 			newy = *y;
@@ -759,9 +754,9 @@ selsnap(int mode, int *x, int *y, int direction) {
 				break;
 
 			gp = &term.line[newy][newx];
-			delim = strchr(worddelimiters, gp->c[0]) != NULL;
+			delim = ISDELIM(gp->u);
 			if(!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
-					|| (delim && gp->c[0] != prevgp->c[0])))
+					|| (delim && gp->u != prevgp->u)))
 				break;
 
 			*x = newx;
@@ -937,7 +932,7 @@ bpress(XEvent *e) {
 char *
 getsel(void) {
 	char *str, *ptr;
-	int y, bufsize, size, lastx, linelen;
+	int y, bufsize, lastx, linelen;
 	Glyph *gp, *last;
 
 	if(sel.ob.x == -1)
@@ -958,16 +953,14 @@ getsel(void) {
 			lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
 		}
 		last = &term.line[y][MIN(lastx, linelen-1)];
-		while(last >= gp && last->c[0] == ' ')
+		while(last >= gp && last->u == ' ')
 			--last;
 
 		for( ; gp <= last; ++gp) {
 			if(gp->mode & ATTR_WDUMMY)
 				continue;
 
-			size = utf8len(gp->c);
-			memcpy(ptr, gp->c, size);
-			ptr += size;
+			ptr += utf8encode(gp->u, ptr);
 		}
 
 		/*
@@ -1277,7 +1270,8 @@ stty(void)
 		siz-= n + 1;
 	}
 	*q = '\0';
-	system(cmd);
+	if (system(cmd) != 0)
+	    perror("Couldn't call stty");
 }
 
 void
@@ -1351,7 +1345,7 @@ ttyread(void) {
 	buflen += ret;
 	ptr = buf;
 	while((charsize = utf8decode(ptr, &unicodep, buflen))) {
-		utf8encode(unicodep, s, UTF_SIZ);
+		utf8encode(unicodep, s);
 		tputc(s, charsize);
 		ptr += charsize;
 		buflen -= charsize;
@@ -1459,7 +1453,7 @@ treset(void) {
 	term.top = 0;
 	term.bot = term.row - 1;
 	term.mode = MODE_WRAP;
-	memset(term.trantbl, sizeof(term.trantbl), CS_USA);
+	memset(term.trantbl, CS_USA, sizeof(term.trantbl));
 	term.charset = 0;
 
 	for(i = 0; i < 2; i++) {
@@ -1643,17 +1637,17 @@ tsetchar(char *c, Glyph *attr, int x, int y) {
 
 	if(term.line[y][x].mode & ATTR_WIDE) {
 		if(x+1 < term.col) {
-			term.line[y][x+1].c[0] = ' ';
+			term.line[y][x+1].u = ' ';
 			term.line[y][x+1].mode &= ~ATTR_WDUMMY;
 		}
 	} else if(term.line[y][x].mode & ATTR_WDUMMY) {
-		term.line[y][x-1].c[0] = ' ';
+		term.line[y][x-1].u = ' ';
 		term.line[y][x-1].mode &= ~ATTR_WIDE;
 	}
 
 	term.dirty[y] = 1;
 	term.line[y][x] = *attr;
-	memcpy(term.line[y][x].c, c, UTF_SIZ);
+	utf8decode(c, &term.line[y][x].u, UTF_SIZ);
 }
 
 void
@@ -1680,7 +1674,7 @@ tclearregion(int x1, int y1, int x2, int y2) {
 			gp->fg = term.c.attr.fg;
 			gp->bg = term.c.attr.bg;
 			gp->mode = 0;
-			memcpy(gp->c, " ", 2);
+			gp->u = ' ';
 		}
 	}
 }
@@ -2269,8 +2263,7 @@ strhandle(void) {
 
 	term.esc &= ~(ESC_STR_END|ESC_STR);
 	strparse();
-	narg = strescseq.narg;
-	par = atoi(strescseq.args[0]);
+	par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0;
 
 	switch(strescseq.type) {
 	case ']': /* OSC -- Operating System Command */
@@ -2401,13 +2394,14 @@ tdumpsel(void) {
 
 void
 tdumpline(int n) {
+	char buf[UTF_SIZ];
 	Glyph *bp, *end;
 
 	bp = &term.line[n][0];
 	end = &bp[MIN(tlinelen(n), term.col) - 1];
-	if(bp != end || bp->c[0] != ' ') {
+	if(bp != end || bp->u != ' ') {
 		for( ;bp <= end; ++bp)
-			tprinter(bp->c, utf8len(bp->c));
+			tprinter(buf, utf8encode(bp->u, buf));
 	}
 	tprinter("\n", 1);
 }
@@ -2790,7 +2784,7 @@ tputc(char *c, int len) {
 	if(width == 2) {
 		gp->mode |= ATTR_WIDE;
 		if(term.c.x+1 < term.col) {
-			gp[1].c[0] = '\0';
+			gp[1].u = '\0';
 			gp[1].mode = ATTR_WDUMMY;
 		}
 	}
@@ -2899,82 +2893,58 @@ sixd_to_16bit(int x) {
 	return x == 0 ? 0 : 0x3737 + 0x2828 * x;
 }
 
+bool
+xloadcolor(int i, const char *name, Color *ncolor) {
+	XRenderColor color = { .alpha = 0xffff };
+
+	if(!name) {
+		if(BETWEEN(i, 16, 255)) { /* 256 color */
+			if(i < 6*6*6+16) { /* same colors as xterm */
+				color.red   = sixd_to_16bit( ((i-16)/36)%6 );
+				color.green = sixd_to_16bit( ((i-16)/6) %6 );
+				color.blue  = sixd_to_16bit( ((i-16)/1) %6 );
+			} else { /* greyscale */
+				color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16));
+				color.green = color.blue = color.red;
+			}
+			return XftColorAllocValue(xw.dpy, xw.vis,
+			                          xw.cmap, &color, ncolor);
+		} else
+			name = colorname[i];
+	}
+	return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
+}
+
 void
 xloadcols(void) {
 	int i;
-	XRenderColor color = { .alpha = 0xffff };
 	static bool loaded;
 	Color *cp;
 
 	if(loaded) {
-		for (cp = dc.col; cp < dc.col + LEN(dc.col); ++cp)
+		for (cp = dc.col; cp < &dc.col[LEN(dc.col)]; ++cp)
 			XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
 	}
 
-	/* load colors [0-15] and [256-LEN(colorname)] (config.h) */
-	for(i = 0; i < LEN(colorname); i++) {
-		if(!colorname[i])
-			continue;
-		if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.col[i])) {
-			die("Could not allocate color '%s'\n", colorname[i]);
+	for(i = 0; i < LEN(dc.col); i++)
+		if(!xloadcolor(i, NULL, &dc.col[i])) {
+			if(colorname[i])
+				die("Could not allocate color '%s'\n", colorname[i]);
+			else
+				die("Could not allocate color %d\n", i);
 		}
-	}
-
-	/* load colors [16-231] ; same colors as xterm */
-	for(i = 16; i < 6*6*6+16; i++) {
-		color.red   = sixd_to_16bit( ((i-16)/36)%6 );
-		color.green = sixd_to_16bit( ((i-16)/6) %6 );
-		color.blue  = sixd_to_16bit( ((i-16)/1) %6 );
-		if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i]))
-			die("Could not allocate color %d\n", i);
-	}
-
-	/* load colors [232-255] ; grayscale */
-	for(; i < 256; i++) {
-		color.red = color.green = color.blue = 0x0808 + 0x0a0a * (i-(6*6*6+16));
-		if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i]))
-			die("Could not allocate color %d\n", i);
-	}
 	loaded = true;
 }
 
 int
 xsetcolorname(int x, const char *name) {
-	XRenderColor color = { .alpha = 0xffff };
 	Color ncolor;
 
-	if(!BETWEEN(x, 0, LEN(colorname)))
+	if(!BETWEEN(x, 0, LEN(dc.col)))
 		return 1;
 
-	if(!name) {
-		if(BETWEEN(x, 16, 16 + 215)) { /* 256 color */
-			color.red   = sixd_to_16bit( ((x-16)/36)%6 );
-			color.green = sixd_to_16bit( ((x-16)/6) %6 );
-			color.blue  = sixd_to_16bit( ((x-16)/1) %6 );
-			if(!XftColorAllocValue(xw.dpy, xw.vis,
-						xw.cmap, &color, &ncolor)) {
-				return 1;
-			}
 
-			XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
-			dc.col[x] = ncolor;
-			return 0;
-		} else if(BETWEEN(x, 16 + 216, 255)) { /* greyscale */
-			color.red = color.green = color.blue = \
-				    0x0808 + 0x0a0a * (x - (16 + 216));
-			if(!XftColorAllocValue(xw.dpy, xw.vis,
-						xw.cmap, &color, &ncolor)) {
-				return 1;
-			}
-
-			XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
-			dc.col[x] = ncolor;
-			return 0;
-		} else { /* system colors */
-			name = colorname[x];
-		}
-	}
-	if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, &ncolor))
+	if(!xloadcolor(x, name, &ncolor))
 		return 1;
 
 	XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
@@ -3577,11 +3547,20 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
 	XftDrawSetClip(xw.draw, 0);
 }
 
+void
+xdrawglyph(Glyph g, int x, int y) {
+	static char buf[UTF_SIZ];
+	size_t len = utf8encode(g.u, buf);
+	int width = g.mode & ATTR_WIDE ? 2 : 1;
+
+	xdraws(buf, g, x, y, width, len);
+}
+
 void
 xdrawcursor(void) {
 	static int oldx = 0, oldy = 0;
-	int sl, width, curx;
-	Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs};
+	int curx;
+	Glyph g = {' ', ATTR_NULL, defaultbg, defaultcs};
 
 	LIMIT(oldx, 0, term.col-1);
 	LIMIT(oldy, 0, term.row-1);
@@ -3594,13 +3573,10 @@ xdrawcursor(void) {
 	if(term.line[term.c.y][curx].mode & ATTR_WDUMMY)
 		curx--;
 
-	memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
+	g.u = term.line[term.c.y][term.c.x].u;
 
 	/* remove the old cursor */
-	sl = utf8len(term.line[oldy][oldx].c);
-	width = (term.line[oldy][oldx].mode & ATTR_WIDE)? 2 : 1;
-	xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
-			oldy, width, sl);
+	xdrawglyph(term.line[oldy][oldx], oldx, oldy);
 
 	if(IS_SET(MODE_HIDE))
 		return;
@@ -3617,10 +3593,8 @@ xdrawcursor(void) {
 						g.bg = defaultfg;
 					}
 
-				sl = utf8len(g.c);
-				width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\
-					? 2 : 1;
-				xdraws(g.c, g, term.c.x, term.c.y, width, sl);
+				g.mode |= term.line[term.c.y][curx].mode & ATTR_WIDE;
+				xdrawglyph(g, term.c.x, term.c.y);
 				break;
 			case 3: /* Blinking Underline */
 			case 4: /* Steady Underline */
@@ -3693,11 +3667,10 @@ draw(void) {
 
 void
 drawregion(int x1, int y1, int x2, int y2) {
-	int ic, ib, x, y, ox, sl;
+	int ic, ib, x, y, ox;
 	Glyph base, new;
 	char buf[DRAW_BUF_SIZ];
 	bool ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
-	long unicodep;
 
 	if(!(xw.state & WIN_VISIBLE))
 		return;
@@ -3726,9 +3699,7 @@ drawregion(int x1, int y1, int x2, int y2) {
 				base = new;
 			}
 
-			sl = utf8decode(new.c, &unicodep, UTF_SIZ);
-			memcpy(buf+ib, new.c, sl);
-			ib += sl;
+			ib += utf8encode(new.u, buf+ib);
 			ic += (new.mode & ATTR_WIDE)? 2 : 1;
 		}
 		if(ib > 0)
@@ -3739,12 +3710,6 @@ drawregion(int x1, int y1, int x2, int y2) {
 
 void
 expose(XEvent *ev) {
-	XExposeEvent *e = &ev->xexpose;
-
-	if(xw.state & WIN_REDRAW) {
-		if(!e->count)
-			xw.state &= ~WIN_REDRAW;
-	}
 	redraw();
 }
 
@@ -3752,12 +3717,7 @@ void
 visibility(XEvent *ev) {
 	XVisibilityEvent *e = &ev->xvisibility;
 
-	if(e->state == VisibilityFullyObscured) {
-		xw.state &= ~WIN_VISIBLE;
-	} else if(!(xw.state & WIN_VISIBLE)) {
-		/* need a full redraw for next Expose, not just a buf copy */
-		xw.state |= WIN_VISIBLE | WIN_REDRAW;
-	}
+	MODBIT(xw.state, e->state != VisibilityFullyObscured, WIN_VISIBLE);
 }
 
 void
@@ -3885,7 +3845,7 @@ kpress(XEvent *ev) {
 		if(IS_SET(MODE_8BIT)) {
 			if(*buf < 0177) {
 				c = *buf | 0x80;
-				len = utf8encode(c, buf, UTF_SIZ);
+				len = utf8encode(c, buf);
 			}
 		} else {
 			buf[1] = buf[0];
@@ -4102,7 +4062,7 @@ run:
 	if(argc > 0) {
 		/* eat all remaining arguments */
 		opt_cmd = argv;
-		if(!opt_title)
+		if(!opt_title && !opt_line)
 			opt_title = basename(xstrdup(argv[0]));
 	}
 	setlocale(LC_CTYPE, "");