# st

Unnamed repository; edit this file 'description' to name the repository.

| Log | Files | Refs | README | LICENSE

    commit f8c6e7d0419d10c1425cb2c7123c5798ffb3b942
    parent 539afe3af1b0d8b56b9ebfaa3bb7fc4e40f68c71
    Author: Christoph Lohmann <20h@r-36.net>
    Date:   Fri, 10 Jul 2015 14:10:17 +0200

    Implement INCR transfers in the clipboard.

    Diffstat:
    Mst.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------

    1 file changed, 68 insertions(+), 6 deletions(-)
    diff --git a/st.c b/st.c
    @@ -452,6 +452,7 @@ static void focus(XEvent *);
     static void brelease(XEvent *);
     static void bpress(XEvent *);
     static void bmotion(XEvent *);
    +static void propnotify(XEvent *);
     static void selnotify(XEvent *);
     static void selclear(XEvent *);
     static void selrequest(XEvent *);
    @@ -500,6 +501,11 @@ static void (*handler[LASTEvent])(XEvent *) = {
      */
     /*	[SelectionClear] = selclear, */
     	[SelectionNotify] = selnotify,
    +/*
    + * PropertyNotify is only turned on when there is some INCR transfer happening
    + * for the selection retrieval.
    + */
    +	[PropertyNotify] = propnotify,
     	[SelectionRequest] = selrequest,
     };

    @@ -1029,20 +1035,40 @@ selcopy(Time t)
     }

     void
    +propnotify(XEvent *e)
    +{
    +	XPropertyEvent *xpev;
    +	Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
    +
    +	xpev = &e->xproperty;
    +	if (xpev->state == PropertyNewValue &&
    +			(xpev->atom == XA_PRIMARY ||
    +			 xpev->atom == clipboard)) {
    +		slenotify(e);
    +	}
    +}
    +
    +void
     selnotify(XEvent *e)
     {
     	ulong nitems, ofs, rem;
     	int format;
     	uchar *data, *last, *repl;
    -	Atom type;
    -	XSelectionEvent *xsev;
    +	Atom type, incratom, property;

     	ofs = 0;
    -	xsev = &e->xselection;
    -	if (xsev->property == None)
    -	    return;
    +	if (e->type == SelectionNotify) {
    +		property = e->xselection.property;
    +	} else if(e->type == PropertyNotify) {
    +		property = e->xproperty.atom;
    +	} else {
    +		return;
    +	}
    +	if (property == None)
    +		return;
    +
     	do {
    -		if (XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs,
    +		if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
     					BUFSIZ/4, False, AnyPropertyType,
     					&type, &format, &nitems, &rem,
     					&data)) {
    @@ -1050,6 +1076,35 @@ selnotify(XEvent *e)
     			return;
     		}

    +		if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
    +			/*
    +			 * If there is some PropertyNotify with no data, then
    +			 * this is the signal of the selection owner that all
    +			 * data has been transferred. We won't need to receive
    +			 * PropertyNotify events anymore.
    +			 */
    +			MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask);
    +			XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
    +					&xw.attrs);
    +		}
    +
    +		if (type == incratom) {
    +			/*
    +			 * Activate the PropertyNotify events so we receive
    +			 * when the selection owner does send us the next
    +			 * chunk of data.
    +			 */
    +			MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
    +			XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
    +					&xw.attrs);
    +
    +			/*
    +			 * Deleting the property is the transfer start signal.
    +			 */
    +			XDeleteProperty(xw.dpy, xw.win, (int)property);
    +			continue;
    +		}
    +
     		/*
     		 * As seen in getsel:
     		 * Line endings are inconsistent in the terminal and GUI world
    @@ -1072,6 +1127,13 @@ selnotify(XEvent *e)
     		/* number of 32-bit chunks returned */
     		ofs += nitems * format / 32;
     	} while (rem > 0);
    +
    +	/*
    +	 * Deleting the property again tells the selection owner to send the
    +	 * next data chunk in the property.
    +	 */
    +	if (e->type == PropertyNotify)
    +		XDeleteProperty(xw.dpy, xw.win, (int)property);
     }

     void