X-Git-Url: https://git.xinqibao.xyz/st.git/blobdiff_plain/323d38da20c8a1d295ab1dbc0fc7ce947ef824e1..33201ac65f74e45b4fa60822ba9a538c3cfa9b25:/x.c?ds=inline

diff --git a/x.c b/x.c
index 04e2e05..76fb910 100644
--- a/x.c
+++ b/x.c
@@ -38,12 +38,16 @@ typedef struct {
 	KeySym k;
 	uint mask;
 	char *s;
-	/* three valued logic variables: 0 indifferent, 1 on, -1 off */
+	/* three-valued logic variables: 0 indifferent, 1 on, -1 off */
 	signed char appkey;    /* application keypad */
 	signed char appcursor; /* application cursor */
-	signed char crlf;      /* crlf mode          */
 } Key;
 
+/* X modifiers */
+#define XK_ANY_MOD    UINT_MAX
+#define XK_NO_MOD     0
+#define XK_SWITCH_MOD (1<<13)
+
 /* function definitions used in config.h */
 static void clipcopy(const Arg *);
 static void clippaste(const Arg *);
@@ -89,6 +93,9 @@ typedef struct {
 
 typedef struct {
 	Atom xtarget;
+	char *primary, *clipboard;
+	struct timespec tclick1;
+	struct timespec tclick2;
 } XSelection;
 
 /* Font structure */
@@ -148,8 +155,8 @@ static void propnotify(XEvent *);
 static void selnotify(XEvent *);
 static void selclear_(XEvent *);
 static void selrequest(XEvent *);
-static void selcopy(Time);
-static void getbuttoninfo(XEvent *);
+static void setsel(char *, Time);
+static void mousesel(XEvent *, int);
 static void mousereport(XEvent *);
 static char *kmap(KeySym, uint);
 static int match(uint, uint);
@@ -229,11 +236,11 @@ clipcopy(const Arg *dummy)
 {
 	Atom clipboard;
 
-	if (sel.clipboard != NULL)
-		free(sel.clipboard);
+	if (xsel.clipboard != NULL)
+		free(xsel.clipboard);
 
-	if (sel.primary != NULL) {
-		sel.clipboard = xstrdup(sel.primary);
+	if (xsel.primary != NULL) {
+		xsel.clipboard = xstrdup(xsel.primary);
 		clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
 		XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime);
 	}
@@ -271,7 +278,6 @@ zoomabs(const Arg *arg)
 	xunloadfonts();
 	xloadfonts(usedfont, arg->f);
 	cresize(0, 0);
-	ttyresize(win.tw, win.th);
 	redraw();
 	xhints();
 }
@@ -306,24 +312,20 @@ y2row(int y)
 }
 
 void
-getbuttoninfo(XEvent *e)
+mousesel(XEvent *e, int done)
 {
-	int type;
+	int type, seltype = SEL_REGULAR;
 	uint state = e->xbutton.state & ~(Button1Mask | forceselmod);
 
-	sel.alt = IS_SET(MODE_ALTSCREEN);
-
-	sel.oe.x = x2col(e->xbutton.x);
-	sel.oe.y = y2row(e->xbutton.y);
-	selnormalize();
-
-	sel.type = SEL_REGULAR;
 	for (type = 1; type < LEN(selmasks); ++type) {
 		if (match(selmasks[type], state)) {
-			sel.type = type;
+			seltype = type;
 			break;
 		}
 	}
+	selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype, done);
+	if (done)
+		setsel(getsel(), e->xbutton.time);
 }
 
 void
@@ -387,7 +389,7 @@ mousereport(XEvent *e)
 		return;
 	}
 
-	ttywrite(buf, len);
+	ttywrite(buf, len, 0);
 }
 
 void
@@ -395,6 +397,7 @@ bpress(XEvent *e)
 {
 	struct timespec now;
 	MouseShortcut *ms;
+	int snap;
 
 	if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
 		mousereport(e);
@@ -404,48 +407,31 @@ bpress(XEvent *e)
 	for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
 		if (e->xbutton.button == ms->b
 				&& match(ms->mask, e->xbutton.state)) {
-			ttysend(ms->s, strlen(ms->s));
+			ttywrite(ms->s, strlen(ms->s), 1);
 			return;
 		}
 	}
 
 	if (e->xbutton.button == Button1) {
-		clock_gettime(CLOCK_MONOTONIC, &now);
-
-		/* Clear previous selection, logically and visually. */
-		selclear_(NULL);
-		sel.mode = SEL_EMPTY;
-		sel.type = SEL_REGULAR;
-		sel.oe.x = sel.ob.x = x2col(e->xbutton.x);
-		sel.oe.y = sel.ob.y = y2row(e->xbutton.y);
-
 		/*
 		 * If the user clicks below predefined timeouts specific
 		 * snapping behaviour is exposed.
 		 */
-		if (TIMEDIFF(now, sel.tclick2) <= tripleclicktimeout) {
-			sel.snap = SNAP_LINE;
-		} else if (TIMEDIFF(now, sel.tclick1) <= doubleclicktimeout) {
-			sel.snap = SNAP_WORD;
+		clock_gettime(CLOCK_MONOTONIC, &now);
+		if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) {
+			snap = SNAP_LINE;
+		} else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) {
+			snap = SNAP_WORD;
 		} else {
-			sel.snap = 0;
+			snap = 0;
 		}
-		selnormalize();
+		xsel.tclick2 = xsel.tclick1;
+		xsel.tclick1 = now;
 
-		if (sel.snap != 0)
-			sel.mode = SEL_READY;
-		tsetdirt(sel.nb.y, sel.ne.y);
-		sel.tclick2 = sel.tclick1;
-		sel.tclick1 = now;
+		selstart(x2col(e->xbutton.x), y2row(e->xbutton.y), snap);
 	}
 }
 
-void
-selcopy(Time t)
-{
-	xsetsel(getsel(), t);
-}
-
 void
 propnotify(XEvent *e)
 {
@@ -533,10 +519,10 @@ selnotify(XEvent *e)
 		}
 
 		if (IS_SET(MODE_BRCKTPASTE) && ofs == 0)
-			ttywrite("\033[200~", 6);
-		ttysend((char *)data, nitems * format / 8);
+			ttywrite("\033[200~", 6, 0);
+		ttywrite((char *)data, nitems * format / 8, 1);
 		if (IS_SET(MODE_BRCKTPASTE) && rem == 0)
-			ttywrite("\033[201~", 6);
+			ttywrite("\033[201~", 6, 0);
 		XFree(data);
 		/* number of 32-bit chunks returned */
 		ofs += nitems * format / 32;
@@ -596,9 +582,9 @@ selrequest(XEvent *e)
 		 */
 		clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
 		if (xsre->selection == XA_PRIMARY) {
-			seltext = sel.primary;
+			seltext = xsel.primary;
 		} else if (xsre->selection == clipboard) {
-			seltext = sel.clipboard;
+			seltext = xsel.clipboard;
 		} else {
 			fprintf(stderr,
 				"Unhandled clipboard selection 0x%lx\n",
@@ -620,16 +606,22 @@ selrequest(XEvent *e)
 }
 
 void
-xsetsel(char *str, Time t)
+setsel(char *str, Time t)
 {
-	free(sel.primary);
-	sel.primary = str;
+	free(xsel.primary);
+	xsel.primary = str;
 
 	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
 	if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
 		selclear_(NULL);
 }
 
+void
+xsetsel(char *str)
+{
+	setsel(str, CurrentTime);
+}
+
 void
 brelease(XEvent *e)
 {
@@ -638,41 +630,21 @@ brelease(XEvent *e)
 		return;
 	}
 
-	if (e->xbutton.button == Button2) {
+	if (e->xbutton.button == Button2)
 		selpaste(NULL);
-	} else if (e->xbutton.button == Button1) {
-		if (sel.mode == SEL_READY) {
-			getbuttoninfo(e);
-			selcopy(e->xbutton.time);
-		} else
-			selclear_(NULL);
-		sel.mode = SEL_IDLE;
-		tsetdirt(sel.nb.y, sel.ne.y);
-	}
+	else if (e->xbutton.button == Button1)
+		mousesel(e, 1);
 }
 
 void
 bmotion(XEvent *e)
 {
-	int oldey, oldex, oldsby, oldsey;
-
 	if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
 		mousereport(e);
 		return;
 	}
 
-	if (!sel.mode)
-		return;
-
-	sel.mode = SEL_READY;
-	oldey = sel.oe.y;
-	oldex = sel.oe.x;
-	oldsby = sel.nb.y;
-	oldsey = sel.ne.y;
-	getbuttoninfo(e);
-
-	if (oldey != sel.oe.y || oldex != sel.oe.x)
-		tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey));
+	mousesel(e, 0);
 }
 
 void
@@ -690,6 +662,7 @@ cresize(int width, int height)
 
 	tresize(col, row);
 	xresize(col, row);
+	ttyresize(win.tw, win.th);
 }
 
 void
@@ -1122,6 +1095,10 @@ xinit(void)
 	xhints();
 	XSync(xw.dpy, False);
 
+	clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1);
+	clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2);
+	xsel.primary = NULL;
+	xsel.clipboard = NULL;
 	xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
 	if (xsel.xtarget == None)
 		xsel.xtarget = XA_STRING;
@@ -1413,7 +1390,6 @@ xdrawcursor(void)
 	static int oldx = 0, oldy = 0;
 	int curx;
 	Glyph g = {' ', ATTR_NULL, defaultbg, defaultcs}, og;
-	int ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
 	Color drawcol;
 
 	LIMIT(oldx, 0, term.col-1);
@@ -1429,7 +1405,7 @@ xdrawcursor(void)
 
 	/* remove the old cursor */
 	og = term.line[oldy][oldx];
-	if (ena_sel && selected(oldx, oldy))
+	if (selected(oldx, oldy))
 		og.mode ^= ATTR_REVERSE;
 	xdrawglyph(og, oldx, oldy);
 
@@ -1443,7 +1419,7 @@ xdrawcursor(void)
 	if (IS_SET(MODE_REVERSE)) {
 		g.mode |= ATTR_REVERSE;
 		g.bg = defaultfg;
-		if (ena_sel && selected(term.c.x, term.c.y)) {
+		if (selected(term.c.x, term.c.y)) {
 			drawcol = dc.col[defaultcs];
 			g.fg = defaultrcs;
 		} else {
@@ -1451,7 +1427,7 @@ xdrawcursor(void)
 			g.fg = defaultcs;
 		}
 	} else {
-		if (ena_sel && selected(term.c.x, term.c.y)) {
+		if (selected(term.c.x, term.c.y)) {
 			drawcol = dc.col[defaultrcs];
 			g.fg = defaultfg;
 			g.bg = defaultrcs;
@@ -1550,7 +1526,6 @@ drawregion(int x1, int y1, int x2, int y2)
 	int i, x, y, ox, numspecs;
 	Glyph base, new;
 	XftGlyphFontSpec *specs;
-	int ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
 
 	if (!(win.state & WIN_VISIBLE))
 		return;
@@ -1569,7 +1544,7 @@ drawregion(int x1, int y1, int x2, int y2)
 			new = term.line[y][x];
 			if (new.mode == ATTR_WDUMMY)
 				continue;
-			if (ena_sel && selected(x, y))
+			if (selected(x, y))
 				new.mode ^= ATTR_REVERSE;
 			if (i > 0 && ATTRCMP(base, new)) {
 				xdrawglyphfontspecs(specs, base, i, ox, y);
@@ -1658,12 +1633,12 @@ focus(XEvent *ev)
 		win.state |= WIN_FOCUSED;
 		xseturgency(0);
 		if (IS_SET(MODE_FOCUS))
-			ttywrite("\033[I", 3);
+			ttywrite("\033[I", 3, 0);
 	} else {
 		XUnsetICFocus(xw.xic);
 		win.state &= ~WIN_FOCUSED;
 		if (IS_SET(MODE_FOCUS))
-			ttywrite("\033[O", 3);
+			ttywrite("\033[O", 3, 0);
 	}
 }
 
@@ -1704,9 +1679,6 @@ kmap(KeySym k, uint state)
 		if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0)
 			continue;
 
-		if (IS_SET(MODE_CRLF) ? kp->crlf < 0 : kp->crlf > 0)
-			continue;
-
 		return kp->s;
 	}
 
@@ -1738,7 +1710,7 @@ kpress(XEvent *ev)
 
 	/* 2. custom keys from config.h */
 	if ((customkey = kmap(ksym, e->state))) {
-		ttysend(customkey, strlen(customkey));
+		ttywrite(customkey, strlen(customkey), 1);
 		return;
 	}
 
@@ -1757,7 +1729,7 @@ kpress(XEvent *ev)
 			len = 2;
 		}
 	}
-	ttysend(buf, len);
+	ttywrite(buf, len, 1);
 }
 
 
@@ -1789,7 +1761,6 @@ resize(XEvent *e)
 		return;
 
 	cresize(e->xconfigure.width, e->xconfigure.height);
-	ttyresize(win.tw, win.th);
 }
 
 void
@@ -1818,9 +1789,8 @@ run(void)
 		}
 	} while (ev.type != MapNotify);
 
-	cresize(w, h);
 	ttynew(opt_line, opt_io, opt_cmd);
-	ttyresize(win.tw, win.th);
+	cresize(w, h);
 
 	clock_gettime(CLOCK_MONOTONIC, &last);
 	lastblink = last;