#include #include #include #include /* GNU */ #include #include #define MAX_PASTE 8192 Window make_input_window(Display *dpy) { return XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, InputOnly, CopyFromParent, 0, 0); } size_t print_clipboard_contents(Display *dpy) { XEvent e; Window w = make_input_window(dpy); /* TODO: check w */ XConvertSelection(dpy, XA_PRIMARY, XA_STRING, XA_STRING, w, CurrentTime); do XNextEvent(dpy, &e); while (e.type != SelectionNotify); if (e.xselection.property != XA_STRING) return 0; { Atom actual_type_return; int actual_format_return; unsigned long nitems_return; unsigned long bytes_after_return; unsigned char *prop_return; int i; for (i=0; i<2; ++i) { if (XGetWindowProperty(dpy, w, XA_STRING, 0, i == 0 ? 0 : bytes_after_return, False, AnyPropertyType, &actual_type_return, &actual_format_return, &nitems_return, &bytes_after_return, &prop_return) != Success) return 0; if (i == 0 && bytes_after_return <= 0) return 0; } return fwrite(prop_return, /* this is just leaked */ actual_format_return / 8, nitems_return, stdout); } } void set_clipboard_contents(Display *dpy, unsigned char *s, size_t len) { Window w = make_input_window(dpy); /* TODO: check w */ XSetSelectionOwner(dpy, XA_PRIMARY, w, CurrentTime); for (;;) { XEvent e, respond; XNextEvent(dpy, &e); if (e.type == SelectionClear) break; if (e.type != SelectionRequest) continue; #define req e.xselectionrequest #define rex respond.xselection rex.type = SelectionNotify; rex.display = req.display; rex.requestor = req.requestor; rex.selection = req.selection; rex.target = req.target; rex.time = req.time; if (req.target == XA_STRING) { XChangeProperty(dpy, req.requestor, req.property != None ? req.property : req.target, XA_STRING, 8, PropModeReplace, s, len); rex.property = req.property; } else rex.property = None; XSendEvent(dpy, req.requestor, 0, 0, &respond); #undef req #undef rex } } int main(int argc, char **argv) { Display *dpy; if (argc > 2 || argc == 2 && strcmp(argv[1], "-paste")) error(1, 0, "Usage: xcopy [-paste]"); if ((dpy = XOpenDisplay(NULL)) == NULL) error(2, 0, "Could not connect to X server"); if (argc == 2) /* -paste */ print_clipboard_contents(dpy); else { char buf[MAX_PASTE]; size_t n = fread(buf, 1, MAX_PASTE, stdin); if (ferror(stdin)) error(3, errno, "fread()"); set_clipboard_contents(dpy, buf, n); } XCloseDisplay(dpy); return 0; }