X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/d018c9c8efc3e1781d84d7b7d24e9531bb841b34..c5a9b799d44be9c0fa4264dc34d9dd61321be795:/st.c

diff --git a/st.c b/st.c
index 0db81f4..397f6a6 100644
--- a/st.c
+++ b/st.c
@@ -53,8 +53,6 @@
 #define XK_NO_MOD     UINT_MAX
 #define XK_ANY_MOD    0
 
-#define SELECT_TIMEOUT (20*1000) /* 20 ms */
-#define DRAW_TIMEOUT  (20*1000) /* 20 ms */
 #define REDRAW_TIMEOUT (80*1000) /* 80 ms */
 
 #define SERRNO strerror(errno)
@@ -205,7 +203,6 @@ typedef struct {
 	int ch; /* char height */
 	int cw; /* char width  */
 	char state; /* focus, redraw, visible */
-	struct timeval lastdraw;
 } XWindow;
 
 typedef struct {
@@ -240,7 +237,7 @@ typedef struct {
 		short lbearing;
 		short rbearing;
 		XFontSet set;
-	} font, bfont, ifont;
+	} font, bfont, ifont, ibfont;
 } DC;
 
 static void die(const char*, ...);
@@ -250,7 +247,6 @@ static void drawregion(int, int, int, int);
 static void execsh(void);
 static void sigchld(int);
 static void run(void);
-static bool last_draw_too_old(void);
 
 static void csidump(void);
 static void csihandle(void);
@@ -292,10 +288,10 @@ static void ttywrite(const char *, size_t);
 static void xdraws(char *, Glyph, int, int, int, int);
 static void xhints(void);
 static void xclear(int, int, int, int);
-static void xcopy(void);
 static void xdrawcursor(void);
 static void xinit(void);
 static void xloadcols(void);
+static void xresettitle(void);
 static void xseturgency(int);
 static void xsetsel(char*);
 static void xresize(int, int);
@@ -638,7 +634,6 @@ void selclear(XEvent *e) {
 		return;
 	sel.bx = -1;
 	tsetdirt(sel.b.y, sel.e.y);
-	draw();
 }
 
 void
@@ -688,8 +683,6 @@ xsetsel(char *str) {
 
 	clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
 	XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime);
-
-	XFlush(xw.dpy);
 }
 
 void
@@ -732,7 +725,6 @@ brelease(XEvent *e) {
 	}
 	memcpy(&sel.tclick2, &sel.tclick1, sizeof(struct timeval));
 	gettimeofday(&sel.tclick1, NULL);
-	draw();
 }
 
 void
@@ -749,7 +741,6 @@ bmotion(XEvent *e) {
 			int starty = MIN(oldey, sel.ey);
 			int endy = MAX(oldey, sel.ey);
 			tsetdirt(starty, endy);
-			draw();
 		}
 	}
 }
@@ -773,6 +764,13 @@ execsh(void) {
 	unsetenv("LINES");
 	unsetenv("TERMCAP");
 
+	signal(SIGCHLD, SIG_DFL);
+	signal(SIGHUP, SIG_DFL);
+	signal(SIGINT, SIG_DFL);
+	signal(SIGQUIT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+	signal(SIGALRM, SIG_DFL);
+
 	DEFAULT(envshell, SHELL);
 	putenv("TERM="TNAME);
 	args = opt_cmd ? opt_cmd : (char*[]){envshell, "-i", NULL};
@@ -1684,6 +1682,7 @@ tputc(char *c) {
 			case 'c': /* RIS -- Reset to inital state */
 				treset();
 				term.esc = 0;
+				xresettitle();
 				break;
 			case '=': /* DECPAM -- Application keypad */
 				term.mode |= MODE_APPKEYPAD;
@@ -1714,6 +1713,8 @@ tputc(char *c) {
 		if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey))
 			sel.bx = -1;
 		switch(ascii) {
+		case '\0': /* padding character, do nothing */
+			break;
 		case '\t':
 			tputtab(1);
 			break;
@@ -1934,13 +1935,15 @@ xgetfontinfo(XFontSet set, int *ascent, int *descent, short *lbearing, short *rb
 }
 
 void
-initfonts(char *fontstr, char *bfontstr, char *ifontstr) {
+initfonts(char *fontstr, char *bfontstr, char *ifontstr, char *ibfontstr) {
 	if((dc.font.set = xinitfont(fontstr)) == NULL)
 		die("Can't load font %s\n", fontstr);
 	if((dc.bfont.set = xinitfont(bfontstr)) == NULL)
 		die("Can't load bfont %s\n", bfontstr);
 	if((dc.ifont.set = xinitfont(ifontstr)) == NULL)
 		die("Can't load ifont %s\n", ifontstr);
+	if((dc.ibfont.set = xinitfont(ibfontstr)) == NULL)
+		die("Can't load ibfont %s\n", ibfontstr);
 
 	xgetfontinfo(dc.font.set, &dc.font.ascent, &dc.font.descent,
 	    &dc.font.lbearing, &dc.font.rbearing);
@@ -1948,6 +1951,8 @@ initfonts(char *fontstr, char *bfontstr, char *ifontstr) {
 	    &dc.bfont.lbearing, &dc.bfont.rbearing);
 	xgetfontinfo(dc.ifont.set, &dc.ifont.ascent, &dc.ifont.descent,
 	    &dc.ifont.lbearing, &dc.ifont.rbearing);
+	xgetfontinfo(dc.ibfont.set, &dc.ibfont.ascent, &dc.ibfont.descent,
+	    &dc.ibfont.lbearing, &dc.ibfont.rbearing);
 }
 
 void
@@ -1955,14 +1960,14 @@ xinit(void) {
 	XSetWindowAttributes attrs;
 	Cursor cursor;
 	Window parent;
-	int sw, sh;
+	int sw, sh, major, minor;
 
 	if(!(xw.dpy = XOpenDisplay(NULL)))
 		die("Can't open display\n");
 	xw.scr = XDefaultScreen(xw.dpy);
 
 	/* font */
-	initfonts(FONT, BOLDFONT, ITALICFONT);
+	initfonts(FONT, BOLDFONT, ITALICFONT, ITALICBOLDFONT);
 
 	/* XXX: Assuming same size for bold font */
 	xw.cw = dc.font.rbearing - dc.font.lbearing;
@@ -2006,9 +2011,10 @@ xinit(void) {
 			CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
 			| CWColormap,
 			&attrs);
+	if(!XdbeQueryExtension(xw.dpy, &major, &minor))
+		die("Xdbe extension is not present\n");
 	xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied);
 
-
 	/* input methods */
 	xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL);
 	xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing
@@ -2026,7 +2032,7 @@ xinit(void) {
 
 	xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
 
-	XStoreName(xw.dpy, xw.win, opt_title ? opt_title : "st");
+	xresettitle();
 	XMapWindow(xw.dpy, xw.win);
 	xhints();
 	XSync(xw.dpy, 0);
@@ -2057,6 +2063,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
 
 	if(base.mode & ATTR_ITALIC)
 		fontset = dc.ifont.set;
+	if(base.mode & (ATTR_ITALIC|ATTR_ITALIC))
+		fontset = dc.ibfont.set;
 
 	XSetBackground(xw.dpy, dc.gc, dc.col[bg]);
 	XSetForeground(xw.dpy, dc.gc, dc.col[fg]);
@@ -2077,13 +2085,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
 		XDrawLine(xw.dpy, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1);
 }
 
-/* copy buffer pixmap to screen pixmap */
-void
-xcopy() {
-	XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}};
-	XdbeSwapBuffers(xw.dpy, swpinfo, 1);
-}
-
 void
 xdrawcursor(void) {
 	static int oldx = 0;
@@ -2104,8 +2105,6 @@ xdrawcursor(void) {
 	} else
 		xclear(oldx, oldy, oldx, oldy);
 
-	xcopy();
-
 	/* draw the new one */
 	if(!(term.c.state & CURSOR_HIDE)) {
 		if(!(xw.state & WIN_FOCUSED))
@@ -2118,8 +2117,11 @@ xdrawcursor(void) {
 		xdraws(g.c, g, term.c.x, term.c.y, 1, sl);
 		oldx = term.c.x, oldy = term.c.y;
 	}
+}
 
-	xcopy();
+void
+xresettitle(void) {
+	XStoreName(xw.dpy, xw.win, opt_title ? opt_title : "st");
 }
 
 void
@@ -2127,14 +2129,16 @@ redraw(void) {
 	struct timespec tv = {0, REDRAW_TIMEOUT * 1000};
 	tfulldirt();
 	draw();
+	XSync(xw.dpy, False); /* necessary for a good tput flash */
 	nanosleep(&tv, NULL);
 }
 
 void
 draw() {
+	XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}};
+
 	drawregion(0, 0, term.col, term.row);
-	xcopy();
-	gettimeofday(&xw.lastdraw, NULL);
+	XdbeSwapBuffers(xw.dpy, swpinfo, 1);
 }
 
 void
@@ -2189,7 +2193,6 @@ expose(XEvent *ev) {
 		if(!e->count)
 			xw.state &= ~WIN_REDRAW;
 	}
-	xcopy();
 }
 
 void
@@ -2222,7 +2225,6 @@ focus(XEvent *ev) {
 		xseturgency(0);
 	} else
 		xw.state &= ~WIN_FOCUSED;
-	draw();
 }
 
 char*
@@ -2298,7 +2300,6 @@ cmessage(XEvent *e) {
 		} else if(e->xclient.data.l[1] == XEMBED_FOCUS_OUT) {
 			xw.state &= ~WIN_FOCUSED;
 		}
-		draw();
 	}
 }
 
@@ -2321,41 +2322,23 @@ resize(XEvent *e) {
 	ttyresize(col, row);
 }
 
-bool
-last_draw_too_old(void) {
-	struct timeval now;
-	gettimeofday(&now, NULL);
-	return TIMEDIFF(now, xw.lastdraw) >= DRAW_TIMEOUT/1000;
-}
-
 void
 run(void) {
 	XEvent ev;
 	fd_set rfd;
 	int xfd = XConnectionNumber(xw.dpy);
-	struct timeval timeout = {0};
-	bool stuff_to_print = 0;
 
 	for(;;) {
 		FD_ZERO(&rfd);
 		FD_SET(cmdfd, &rfd);
 		FD_SET(xfd, &rfd);
-		timeout.tv_sec  = 0;
-		timeout.tv_usec = SELECT_TIMEOUT;
-		if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, &timeout) < 0) {
+		if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL) < 0) {
 			if(errno == EINTR)
 				continue;
 			die("select failed: %s\n", SERRNO);
 		}
-		if(FD_ISSET(cmdfd, &rfd)) {
+		if(FD_ISSET(cmdfd, &rfd))
 			ttyread();
-			stuff_to_print = 1;
-		}
-
-		if(stuff_to_print && last_draw_too_old()) {
-			stuff_to_print = 0;
-			draw();
-		}
 
 		while(XPending(xw.dpy)) {
 			XNextEvent(xw.dpy, &ev);
@@ -2364,6 +2347,9 @@ run(void) {
 			if(handler[ev.type])
 				(handler[ev.type])(&ev);
 		}
+
+		draw();
+		XFlush(xw.dpy);
 	}
 }