Implement INCR transfers in the clipboard. - st - Personal fork of st
 (HTM) git clone git://git.drkhsh.at/st.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f8c6e7d0419d10c1425cb2c7123c5798ffb3b942
 (DIR) parent 539afe3af1b0d8b56b9ebfaa3bb7fc4e40f68c71
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Fri, 10 Jul 2015 14:10:17 +0200
       
       Implement INCR transfers in the clipboard.
       
       Diffstat:
         M st.c                                |      74 ++++++++++++++++++++++++++++---
       
       1 file changed, 68 insertions(+), 6 deletions(-)
       ---
 (DIR) 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