hi st users,

here is a patch to support xclipboard st.
the code was extracted and adapted from x11.c of qemacs.
please try and if there is something to change, Iet me know.

pd: Aurélien, thanks for accepting my previous patch.
pd2: sorry my bad english.

saludos
-f
# HG changeset patch
# User fl
# Date 1286656688 10800
# Node ID 3be141f80d5ac30dd786dafc3769964c62d2e887
# Parent  96c41df08c947e720ad46ca4adadd5f4e59a0108
xclipboard support

diff -r 96c41df08c94 -r 3be141f80d5a st.c
--- a/st.c	Tue Sep 21 16:04:13 2010 +0200
+++ b/st.c	Sat Oct 09 17:38:08 2010 -0300
@@ -18,6 +18,7 @@
 #include <unistd.h>
 #include <X11/Xlib.h>
 #include <X11/keysym.h>
+#include <X11/Xatom.h>
 #include <X11/Xutil.h>
 
 #if   defined(__linux)
@@ -199,6 +200,8 @@
 static void brelease(XEvent *);
 static void bpress(XEvent *);
 static void bmotion(XEvent *);
+static void selsend(XEvent *);
+static void selclear(XEvent *);
 
 
 static void (*handler[LASTEvent])(XEvent *) = {
@@ -212,6 +215,8 @@
 	[MotionNotify] = bmotion,
 	[ButtonPress] = bpress,
 	[ButtonRelease] = brelease,
+	[SelectionRequest] = selsend,
+	[SelectionClear] = selclear,
 };
 
 /* Globals */
@@ -277,15 +282,119 @@
 	return str;
 }
 
-/* TODO: use X11 clipboard */
+/* use X11 clipboard */
 static void selcopy(char *str) {
+	static Atom xa_clipboard = None;
+
 	free(sel.clip);
 	sel.clip = str;
+
+    	/* own selection from now */
+    	XSetSelectionOwner(xw.dis, XA_PRIMARY, xw.win, CurrentTime);
+
+	/* Ctrl-V request support */
+	if (xa_clipboard == None) /* avoid Xmu */
+		xa_clipboard = XInternAtom(xw.dis, "CLIPBOARD", False);
+    	XSetSelectionOwner(xw.dis, xa_clipboard, xw.win, CurrentTime); 
+}
+
+static Bool seltest(Display *dpy, XEvent *ev, char *arg) {
+	return (ev->type == SelectionNotify);
 }
 
 static void selpaste() {
-	if(sel.clip)
+	Window w;
+	Atom prop;
+	unsigned long nread, bytes_after, nitems;
+	unsigned char *data;
+	Atom actual_type;
+	int actual_fmt;
+	XEvent xev;
+
+	w = XGetSelectionOwner(xw.dis, XA_PRIMARY);
+	if (w == None)
+		return;
+	/* st is the owner, directly write sel.clip */
+ 	if (w == xw.win && sel.clip) { 
 		ttywrite(sel.clip, strlen(sel.clip));
+		return;
+	}
+
+	/* use X11 selection (Will be pasted when receiving 
+		SelectionNotify event) */
+	prop = XInternAtom(xw.dis, "VT_SELECTION", False);
+	XConvertSelection(xw.dis, XA_PRIMARY, XA_STRING, 
+		prop, xw.win, CurrentTime);
+
+	/* XXX: add timeout too if the target application 
+		is not well educated */
+	XIfEvent(xw.dis, &xev, seltest, NULL);
+
+	w = xev.xselection.requestor;
+	prop = xev.xselection.property;
+
+	nread = 0;
+	for(;;) {
+		if ((XGetWindowProperty(xw.dis, w, prop, nread/4, 4096, 
+			True, AnyPropertyType, &actual_type, &actual_fmt, 
+			&nitems, &bytes_after, &data) != Success)
+           		|| (actual_type != XA_STRING)) {
+           		XFree (data);
+           		break;
+        	}
+        
+		ttywrite((char*) data, nitems);
+       
+		nread += nitems;
+		XFree (data);
+	}
+}
+
+/* send selection to requestor */
+static void selsend(XEvent *xev)
+{
+	static Atom xa_targets = None;
+	XSelectionRequestEvent *rq = (XSelectionRequestEvent *) xev;
+	XEvent ev;
+
+	if (xa_targets == None)
+		xa_targets = XInternAtom (xw.dis, "TARGETS", False);
+	
+	ev.xselection.type      = SelectionNotify;
+	ev.xselection.property  = None;
+	ev.xselection.display   = rq->display;
+	ev.xselection.requestor = rq->requestor;
+	ev.xselection.selection = rq->selection;
+	ev.xselection.target    = rq->target;
+	ev.xselection.time      = rq->time;
+
+	if (rq->target == xa_targets) {
+		unsigned int target_list[2];
+
+		/* indicate which are supported types */
+		target_list[0] = xa_targets;
+		target_list[1] = XA_STRING;
+
+		XChangeProperty (xw.dis, rq->requestor, rq->property,
+			xa_targets, 8 * sizeof(target_list[0]), PropModeReplace,
+			(unsigned char *) target_list,
+			sizeof(target_list) / sizeof(target_list[0]));
+	} else if (rq->target == XA_STRING) {
+		/* get selection buffer */
+	
+		if (!sel.clip)
+			return; 
+
+		XChangeProperty (xw.dis, rq->requestor, rq->property,
+			XA_STRING, 8, PropModeReplace,
+			(unsigned char *)sel.clip, strlen(sel.clip));
+	}
+	ev.xselection.property = rq->property;
+	XSendEvent (xw.dis, rq->requestor, False, 0, &ev);
+}
+
+static void selclear(XEvent *e) {
+	/* TODO */
 }
 
 /* TODO: doubleclick to select word */

Reply via email to