+static void selection_notify(XEvent *e) {
+ unsigned long nitems;
+ unsigned long ofs, rem;
+ int format;
+ unsigned char *data;
+ Atom type;
+
+ ofs = 0;
+ do {
+ if(XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, ofs, BUFSIZ/4,
+ False, AnyPropertyType, &type, &format,
+ &nitems, &rem, &data)) {
+ fprintf(stderr, "Clipboard allocation failed\n");
+ return;
+ }
+ ttywrite((const char *) data, nitems * format / 8);
+ XFree(data);
+ /* number of 32-bit chunks returned */
+ ofs += nitems * format / 32;
+ } while(rem > 0);
+}
+
+static void selpaste() {
+ XConvertSelection(xw.dis, XA_PRIMARY, XA_STRING, XA_PRIMARY, xw.win, CurrentTime);
+}
+
+static void selection_request(XEvent *e)
+{
+ XSelectionRequestEvent *xsre;
+ XSelectionEvent xev;
+ Atom xa_targets;
+
+ xsre = (XSelectionRequestEvent *) e;
+ xev.type = SelectionNotify;
+ xev.requestor = xsre->requestor;
+ xev.selection = xsre->selection;
+ xev.target = xsre->target;
+ xev.time = xsre->time;
+ /* reject */
+ xev.property = None;
+
+ xa_targets = XInternAtom(xw.dis, "TARGETS", 0);
+ if(xsre->target == xa_targets) {
+ /* respond with the supported type */
+ Atom string = XA_STRING;
+ XChangeProperty(xsre->display, xsre->requestor, xsre->property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) &string, 1);
+ xev.property = xsre->property;
+ } else if(xsre->target == XA_STRING) {
+ XChangeProperty(xsre->display, xsre->requestor, xsre->property,
+ xsre->target, 8, PropModeReplace,
+ (unsigned char *) sel.clip, strlen(sel.clip));
+ xev.property = xsre->property;
+ }
+
+ /* all done, send a notification to the listener */
+ if(!XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *) &xev))
+ fprintf(stderr, "Error sending SelectionNotify event\n");
+}
+