X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=004220476a3af0ff275c2b8d5b87dfc8f05e36dd;hb=68d8fcf62a4f016c0292db543c1c2e694afc5b54;hp=5d5ac301b4b7bfe4a73fcc6a2fafea66bb0fe2df;hpb=3a50a4fd931ed58454b680c9fc5c1bc2278e67f3;p=st.git diff --git a/st.c b/st.c index 5d5ac30..0042204 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 */ @@ -278,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 */ @@ -559,7 +677,7 @@ tsetchar(char c) { void tclearregion(int x1, int y1, int x2, int y2) { - int y, temp; + int x, y, temp; if(x1 > x2) temp = x1, x1 = x2, x2 = temp; @@ -572,7 +690,8 @@ tclearregion(int x1, int y1, int x2, int y2) { LIMIT(y2, 0, term.row-1); for(y = y1; y <= y2; y++) - memset(&term.line[y][x1], 0, sizeof(Glyph)*(x2-x1+1)); + for(x = x1; x <= x2; x++) + term.line[y][x].state = 0; } void @@ -1074,7 +1193,7 @@ tputs(char *s, int len) { void tresize(int col, int row) { - int i; + int i, x; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); int slide = term.c.y - row + 1; @@ -1108,8 +1227,10 @@ tresize(int col, int row) { for(i = 0; i < minrow; i++) { term.line[i] = realloc(term.line[i], col * sizeof(Glyph)); term.alt[i] = realloc(term.alt[i], col * sizeof(Glyph)); - memset(term.line[i] + mincol, 0, (col - mincol) * sizeof(Glyph)); - memset(term.alt[i] + mincol, 0, (col - mincol) * sizeof(Glyph)); + for(x = mincol; x < col; x++) { + term.line[i][x].state = 0; + term.alt[i][x].state = 0; + } } /* allocate any new rows */ @@ -1445,7 +1566,7 @@ kpress(XEvent *ev) { break; case XK_Insert: if(shift) - selpaste(), draw(1); + selpaste(); break; default: fprintf(stderr, "errkey: %d\n", (int)ksym);