X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/15c2bff9faa87644abf96c19b17133d03d40b974..384fabdb5b2ac6c700a974a7fac539c8c14107f6:/st.c?ds=sidebyside

diff --git a/st.c b/st.c
index 7b0fb21..38cec50 100644
--- a/st.c
+++ b/st.c
@@ -44,7 +44,7 @@
 #endif
 
 #define USAGE \
-	"st " VERSION " (c) 2010-2012 st engineers\n" \
+	"st " VERSION " (c) 2010-2013 st engineers\n" \
 	"usage: st [-v] [-c class] [-f font] [-g geometry] [-o file]" \
 	" [-t title] [-w windowid] [-e command ...]\n"
 
@@ -117,7 +117,8 @@ enum term_mode {
 	MODE_KBDLOCK     = 256,
 	MODE_HIDE	 = 512,
 	MODE_ECHO	 = 1024,
-	MODE_APPCURSOR	 = 2048
+	MODE_APPCURSOR	 = 2048,
+	MODE_MOUSESGR    = 4096,
 };
 
 enum escape_state {
@@ -152,7 +153,7 @@ typedef struct {
 	uchar state; /* state flags    */
 } Glyph;
 
-typedef Glyph* Line;
+typedef Glyph *Line;
 
 typedef struct {
 	Glyph attr;	 /* current char attributes */
@@ -303,7 +304,7 @@ static void strhandle(void);
 static void strparse(void);
 static void strreset(void);
 
-static void tclearregion(int, int, int, int);
+static void tclearregion(int, int, int, int, int);
 static void tcursor(int);
 static void tdeletechar(int);
 static void tdeleteline(int);
@@ -666,11 +667,10 @@ getbuttoninfo(XEvent *e) {
 
 void
 mousereport(XEvent *e) {
-	int x = x2col(e->xbutton.x);
-	int y = y2row(e->xbutton.y);
-	int button = e->xbutton.button;
-	int state = e->xbutton.state;
-	char buf[] = { '\033', '[', 'M', 0, 32+x+1, 32+y+1 };
+	int x = x2col(e->xbutton.x), y = y2row(e->xbutton.y),
+	    button = e->xbutton.button, state = e->xbutton.state,
+	    len;
+	char buf[40];
 	static int ob, ox, oy;
 
 	/* from urxvt */
@@ -679,7 +679,9 @@ mousereport(XEvent *e) {
 			return;
 		button = ob + 32;
 		ox = x, oy = y;
-	} else if(e->xbutton.type == ButtonRelease || button == AnyButton) {
+	} else if(!IS_SET(MODE_MOUSESGR)
+			&& (e->xbutton.type == ButtonRelease
+				|| button == AnyButton)) {
 		button = 3;
 	} else {
 		button -= Button1;
@@ -691,11 +693,23 @@ mousereport(XEvent *e) {
 		}
 	}
 
-	buf[3] = 32 + button + (state & ShiftMask ? 4 : 0)
+	button += (state & ShiftMask   ? 4  : 0)
 		+ (state & Mod4Mask    ? 8  : 0)
 		+ (state & ControlMask ? 16 : 0);
 
-	ttywrite(buf, sizeof(buf));
+	len = 0;
+	if(IS_SET(MODE_MOUSESGR)) {
+		len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
+				button, x+1, y+1,
+				e->xbutton.type == ButtonRelease ? 'm' : 'M');
+	} else if(x < 223 && y < 223) {
+		len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
+				32+button, 32+x+1, 32+y+1);
+	} else {
+		return;
+	}
+
+	ttywrite(buf, len);
 }
 
 void
@@ -793,6 +807,7 @@ void selclear(XEvent *e) {
 
 void
 selrequest(XEvent *e) {
+	fprintf(stderr, "selrequest\n");
 	XSelectionRequestEvent *xsre;
 	XSelectionEvent xev;
 	Atom xa_targets, string;
@@ -828,6 +843,7 @@ selrequest(XEvent *e) {
 
 void
 xsetsel(char *str) {
+	fprintf(stderr, "xsetsel: %s\n", str);
 	/* register the selection for both the clipboard and the primary */
 	Atom clipboard;
 
@@ -1113,7 +1129,7 @@ treset(void) {
 	term.bot = term.row - 1;
 	term.mode = MODE_WRAP;
 
-	tclearregion(0, 0, term.col-1, term.row-1);
+	tclearregion(0, 0, term.col-1, term.row-1, 0);
 	tmoveto(0, 0);
 	tcursor(CURSOR_SAVE);
 }
@@ -1157,7 +1173,7 @@ tscrolldown(int orig, int n) {
 
 	LIMIT(n, 0, term.bot-orig+1);
 
-	tclearregion(0, term.bot-n+1, term.col-1, term.bot);
+	tclearregion(0, term.bot-n+1, term.col-1, term.bot, 0);
 
 	for(i = term.bot; i >= orig+n; i--) {
 		temp = term.line[i];
@@ -1177,7 +1193,7 @@ tscrollup(int orig, int n) {
 	Line temp;
 	LIMIT(n, 0, term.bot-orig+1);
 
-	tclearregion(0, orig, term.col-1, orig+n-1);
+	tclearregion(0, orig, term.col-1, orig+n-1, 0);
 
 	for(i = orig; i <= term.bot-n; i++) {
 		 temp = term.line[i];
@@ -1305,7 +1321,7 @@ tsetchar(char *c, Glyph *attr, int x, int y) {
 }
 
 void
-tclearregion(int x1, int y1, int x2, int y2) {
+tclearregion(int x1, int y1, int x2, int y2, int bce) {
 	int x, y, temp;
 
 	if(x1 > x2)
@@ -1320,8 +1336,15 @@ tclearregion(int x1, int y1, int x2, int y2) {
 
 	for(y = y1; y <= y2; y++) {
 		term.dirty[y] = 1;
-		for(x = x1; x <= x2; x++)
-			term.line[y][x].state = 0;
+		for(x = x1; x <= x2; x++) {
+			if(bce) {
+				term.line[y][x] = term.c.attr;
+				memcpy(term.line[y][x].c, " ", 2);
+				term.line[y][x].state |= GLYPH_SET;
+			} else {
+				term.line[y][x].state = 0;
+			}
+		}
 	}
 }
 
@@ -1334,13 +1357,13 @@ tdeletechar(int n) {
 	term.dirty[term.c.y] = 1;
 
 	if(src >= term.col) {
-		tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
+		tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 0);
 		return;
 	}
 
 	memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
 			size * sizeof(Glyph));
-	tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
+	tclearregion(term.col-n, term.c.y, term.col-1, term.c.y, 0);
 }
 
 void
@@ -1352,13 +1375,13 @@ tinsertblank(int n) {
 	term.dirty[term.c.y] = 1;
 
 	if(dst >= term.col) {
-		tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
+		tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 0);
 		return;
 	}
 
 	memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
 			size * sizeof(Glyph));
-	tclearregion(src, term.c.y, dst - 1, term.c.y);
+	tclearregion(src, term.c.y, dst - 1, term.c.y, 0);
 }
 
 void
@@ -1538,12 +1561,17 @@ tsetmode(bool priv, bool set, int *args, int narg) {
 			case 1002:
 				MODBIT(term.mode, set, MODE_MOUSEMOTION);
 				break;
+			case 1006:
+				MODBIT(term.mode, set, MODE_MOUSESGR);
+				break;
 			case 1049: /* = 1047 and 1048 */
 			case 47:
 			case 1047: {
 				alt = IS_SET(MODE_ALTSCREEN);
-				if(alt)
-					tclearregion(0, 0, term.col-1, term.row-1);
+				if(alt) {
+					tclearregion(0, 0, term.col-1,
+							term.row-1, 0);
+				}
 				if(set ^ alt)		/* set is always 1 or 0 */
 					tswapscreen();
 				if(*args != 1049)
@@ -1662,17 +1690,19 @@ csihandle(void) {
 		sel.bx = -1;
 		switch(csiescseq.arg[0]) {
 		case 0: /* below */
-			tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
-			if(term.c.y < term.row-1)
-				tclearregion(0, term.c.y+1, term.col-1, term.row-1);
+			tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1);
+			if(term.c.y < term.row-1) {
+				tclearregion(0, term.c.y+1, term.col-1,
+						term.row-1, 1);
+			}
 			break;
 		case 1: /* above */
 			if(term.c.y > 1)
-				tclearregion(0, 0, term.col-1, term.c.y-1);
-			tclearregion(0, term.c.y, term.c.x, term.c.y);
+				tclearregion(0, 0, term.col-1, term.c.y-1, 1);
+			tclearregion(0, term.c.y, term.c.x, term.c.y, 1);
 			break;
 		case 2: /* all */
-			tclearregion(0, 0, term.col-1, term.row-1);
+			tclearregion(0, 0, term.col-1, term.row-1, 1);
 			break;
 		default:
 			goto unknown;
@@ -1681,13 +1711,14 @@ csihandle(void) {
 	case 'K': /* EL -- Clear line */
 		switch(csiescseq.arg[0]) {
 		case 0: /* right */
-			tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
+			tclearregion(term.c.x, term.c.y, term.col-1,
+					term.c.y, 1);
 			break;
 		case 1: /* left */
-			tclearregion(0, term.c.y, term.c.x, term.c.y);
+			tclearregion(0, term.c.y, term.c.x, term.c.y, 1);
 			break;
 		case 2: /* all */
-			tclearregion(0, term.c.y, term.col-1, term.c.y);
+			tclearregion(0, term.c.y, term.col-1, term.c.y, 1);
 			break;
 		}
 		break;
@@ -1712,7 +1743,8 @@ csihandle(void) {
 		break;
 	case 'X': /* ECH -- Erase <n> char */
 		DEFAULT(csiescseq.arg[0], 1);
-		tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0], term.c.y);
+		tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0],
+				term.c.y, 0);
 		break;
 	case 'P': /* DCH -- Delete <n> char */
 		DEFAULT(csiescseq.arg[0], 1);
@@ -1987,10 +2019,13 @@ tputc(char *c, int len) {
 			term.esc = ESC_START;
 			return;
 		case '\016':	/* SO */
-			term.c.attr.mode |= ATTR_GFX;
-			return;
 		case '\017':	/* SI */
-			term.c.attr.mode &= ~ATTR_GFX;
+			/*
+			 * Different charsets are hard to handle. Applications
+			 * should use the right alt charset escapes for the
+			 * only reason they still exist: line drawing. The
+			 * rest is incompatible history st should not support.
+			 */
 			return;
 		case '\032':	/* SUB */
 		case '\030':	/* CAN */
@@ -2463,6 +2498,7 @@ xzoom(const Arg *arg)
 void
 xinit(void) {
 	XSetWindowAttributes attrs;
+	XGCValues gcvalues;
 	Cursor cursor;
 	Window parent;
 	int sw, sh, major, minor;
@@ -2502,6 +2538,7 @@ xinit(void) {
 		xw.fy = 0;
 	}
 
+	/* Events */
 	attrs.background_pixel = dc.col[defaultbg].pixel;
 	attrs.border_pixel = dc.col[defaultbg].pixel;
 	attrs.bit_gravity = NorthWestGravity;
@@ -2527,7 +2564,10 @@ xinit(void) {
 		usedbe = True;
 	} else {
 	*/
-		dc.gc = XCreateGC(xw.dpy, parent, 0, 0);
+		memset(&gcvalues, 0, sizeof(gcvalues));
+		gcvalues.graphics_exposures = False;
+		dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
+				&gcvalues);
 		xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
 				DefaultDepth(xw.dpy, xw.scr));
 		XSetForeground(xw.dpy, dc.gc, 0);
@@ -2855,7 +2895,6 @@ draw(void) {
 		XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, xw.w,
 				xw.h, 0, 0);
 		XSetForeground(xw.dpy, dc.gc, 0);
-		XSync(xw.dpy, False);
 	}
 }
 
@@ -2895,6 +2934,7 @@ drawregion(int x1, int y1, int x2, int y2) {
 					ox = x;
 					base = new;
 				}
+
 				sl = utf8size(new.c);
 				memcpy(buf+ib, new.c, sl);
 				ib += sl;