From 9eb70a2d3ecbd96a92e5f824868500baba74b688 Mon Sep 17 00:00:00 2001
From: "noname@inventati.org" <noname@inventati.org>
Date: Mon, 13 Apr 2015 14:03:35 +0200
Subject: [PATCH 1/2] Do not use tmoveto in tputtab.

tmoveto resets CURSOR_WRAPNEXT.

Simple testcase:

for i in $(seq 1 200); do
	printf '\t.';
	usleep 100000;
	printf '\t@';
	usleep 100000;
done

In st executing this script causes @ and . to overwrite each other in
the last column.
---
 st.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/st.c b/st.c
index 6d20977..7051a4a 100644
--- a/st.c
+++ b/st.c
@@ -2390,7 +2390,7 @@ tputtab(int n) {
 			for(--x; x > 0 && !term.tabs[x]; --x)
 				/* nothing */ ;
 	}
-	tmoveto(x, term.c.y);
+	term.c.x = LIMIT(x, 0, term.col-1);
 }
 
 void

From 42fa1f5ce46593a9d6c2f9196c1aae1a60ca07d1 Mon Sep 17 00:00:00 2001
From: Markus Wichmann <nullplan@gmx.net>
Date: Sat, 11 Apr 2015 21:21:34 +0200
Subject: [PATCH 2/2] Implement most ICCCM rules for selection handling.

ICCCM mandates the use of real timestamps to interact with the
selection, to rule out race conditions if the clients are run at
different speeds. I have implemented the low hanging fruit, putting the
timestamps into text selection. Also, ICCCM mandates a check for whether
XSetSelectionOwner() worked. Not sure my version is correct, though.
---
 st.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/st.c b/st.c
index f874127..6bfa834 100644
--- a/st.c
+++ b/st.c
@@ -423,7 +423,7 @@ static void xsettitle(char *);
 static void xresettitle(void);
 static void xsetpointermotion(int);
 static void xseturgency(int);
-static void xsetsel(char *);
+static void xsetsel(char *, Time);
 static void xtermclear(int, int, int, int);
 static void xunloadfont(Font *);
 static void xunloadfonts(void);
@@ -449,7 +449,7 @@ static void selinit(void);
 static void selnormalize(void);
 static inline bool selected(int, int);
 static char *getsel(void);
-static void selcopy(void);
+static void selcopy(Time);
 static void selscroll(int, int);
 static void selsnap(int, int *, int *, int);
 static int x2col(int);
@@ -984,8 +984,8 @@ getsel(void) {
 }
 
 void
-selcopy(void) {
-	xsetsel(getsel());
+selcopy(Time t) {
+	xsetsel(getsel(), t);
 }
 
 void
@@ -997,7 +997,7 @@ selnotify(XEvent *e) {
 	XSelectionEvent *xsev;
 
 	ofs = 0;
-	xsev = (XSelectionEvent *)e;
+	xsev = &e->xselection;
 	if (xsev->property == None)
 	    return;
 	do {
@@ -1083,6 +1083,9 @@ selrequest(XEvent *e) {
 	xev.selection = xsre->selection;
 	xev.target = xsre->target;
 	xev.time = xsre->time;
+        if (xsre->property == None)
+            xsre->property = xsre->target;
+
 	/* reject */
 	xev.property = None;
 
@@ -1125,11 +1128,13 @@ selrequest(XEvent *e) {
 }
 
 void
-xsetsel(char *str) {
+xsetsel(char *str, Time t) {
 	free(sel.primary);
 	sel.primary = str;
 
-	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime);
+	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
+        if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
+            selclear(0);
 }
 
 void
@@ -1146,7 +1151,7 @@ brelease(XEvent *e) {
 			selclear(NULL);
 		} else {
 			getbuttoninfo(e);
-			selcopy();
+			selcopy(e->xbutton.time);
 		}
 		sel.mode = 0;
 		tsetdirt(sel.nb.y, sel.ne.y);