X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=37c404877f78f4f7d3db8e614636d0de7905157d;hb=e4bf56ae1a9e2612ec9a6faf2aaecd6eadcccaa7;hp=d1b90efe11b54c82dd7273d91ae33756840c3657;hpb=3470e3af23f4b98ce4293f6090c8df59a08329d9;p=st.git diff --git a/st.c b/st.c index d1b90ef..37c4048 100644 --- a/st.c +++ b/st.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -199,7 +200,8 @@ static void focus(XEvent *); static void brelease(XEvent *); static void bpress(XEvent *); static void bmotion(XEvent *); - +static void selection_notify(XEvent *); +static void selection_request(XEvent *); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, @@ -212,6 +214,8 @@ static void (*handler[LASTEvent])(XEvent *) = { [MotionNotify] = bmotion, [ButtonPress] = bpress, [ButtonRelease] = brelease, + [SelectionNotify] = selection_notify, + [SelectionRequest] = selection_request, }; /* Globals */ @@ -243,8 +247,9 @@ static inline int selected(int x, int y) { } static void getbuttoninfo(XEvent *e, int *b, int *x, int *y) { - if(b) *b = e->xbutton.state, - *b=*b==4096?5:*b==2048?4:*b==1024?3:*b==512?2:*b==256?1:-1; + if(b) + *b = e->xbutton.button; + *x = e->xbutton.x/xw.cw; *y = e->xbutton.y/xw.ch; sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex; @@ -277,15 +282,129 @@ static char *getseltext() { return str; } -/* TODO: use X11 clipboard */ +static void selection_notify(XEvent *e) { + unsigned long nitems; + unsigned long length; + int format, res; + unsigned char *data; + Atom type; + + res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, 0, False, + AnyPropertyType, &type, &format, &nitems, &length, &data); + switch(res) { + case BadAtom: + case BadValue: + case BadWindow: + fprintf(stderr, "Invalid paste, XGetWindowProperty0"); + return; + } + + res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, length, False, + AnyPropertyType, &type, &format, &nitems, &length, &data); + switch(res) { + case BadAtom: + case BadValue: + case BadWindow: + fprintf(stderr, "Invalid paste, XGetWindowProperty0"); + return; + } + + if(data) { + ttywrite((const char *) data, nitems * format / 8); + XFree(data); + } +} + +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; + int res; + 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; + res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, + PropModeReplace, (unsigned char *) &string, 1); + switch(res) { + case BadAlloc: + case BadAtom: + case BadMatch: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_request, TARGETS"); + break; + default: + xev.property = xsre->property; + } + } else if(xsre->target == XA_STRING) { + res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, + xsre->target, 8, PropModeReplace, (unsigned char *) sel.clip, + strlen(sel.clip)); + switch(res) { + case BadAlloc: + case BadAtom: + case BadMatch: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_request, XA_STRING"); + break; + default: + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + res = XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *) &xev); + switch(res) { + case 0: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_requested, XSendEvent"); + } +} + static void selcopy(char *str) { + /* register the selection for both the clipboard and the primary */ + Atom clipboard; + int res; + free(sel.clip); sel.clip = str; -} -static void selpaste() { - if(sel.clip) - ttywrite(sel.clip, strlen(sel.clip)); + res = XSetSelectionOwner(xw.dis, XA_PRIMARY, xw.win, CurrentTime); + switch(res) { + case BadAtom: + case BadWindow: + fprintf(stderr, "Invalid copy, XSetSelectionOwner"); + return; + } + + clipboard = XInternAtom(xw.dis, "CLIPBOARD", 0); + res = XSetSelectionOwner(xw.dis, clipboard, xw.win, CurrentTime); + switch(res) { + case BadAtom: + case BadWindow: + fprintf(stderr, "Invalid copy, XSetSelectionOwner"); + return; + } + + XFlush(xw.dis); } /* TODO: doubleclick to select word */ @@ -1444,7 +1563,7 @@ kpress(XEvent *ev) { break; case XK_Insert: if(shift) - selpaste(), draw(1); + selpaste(); break; default: fprintf(stderr, "errkey: %d\n", (int)ksym);