From 0335ceaeb695ab5e92d0d0cd1f554373056c8696 Mon Sep 17 00:00:00 2001 From: rsc Date: Thu, 3 May 2007 19:13:56 +0000 Subject: try for utf8 string first in getsnarf; new test program snarf --- src/cmd/devdraw/mkfile | 2 + src/cmd/devdraw/snarf.c | 110 +++++++++++++++++++++++++++++++++++++++++++ src/cmd/devdraw/x11-itrans.c | 100 ++++++++++++++++++++++----------------- 3 files changed, 168 insertions(+), 44 deletions(-) create mode 100644 src/cmd/devdraw/snarf.c (limited to 'src') diff --git a/src/cmd/devdraw/mkfile b/src/cmd/devdraw/mkfile index 3952b869..4e4a4476 100644 --- a/src/cmd/devdraw/mkfile +++ b/src/cmd/devdraw/mkfile @@ -18,3 +18,5 @@ HFILES=\ $O.drawclient: drawclient.$O drawfcall.$O $LD -o $target $prereq +$O.snarf: x11-alloc.$O x11-cload.$O x11-draw.$O x11-fill.$O x11-get.$O x11-init.$O x11-itrans.$O x11-keysym2ucs.$O x11-load.$O x11-pixelbits.$O x11-unload.$O x11-wsys.$O snarf.$O latin1.$O devdraw.$O + $LD -o $target $prereq diff --git a/src/cmd/devdraw/snarf.c b/src/cmd/devdraw/snarf.c new file mode 100644 index 00000000..1e7a93a1 --- /dev/null +++ b/src/cmd/devdraw/snarf.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include "x11-inc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "x11-memdraw.h" +#include "devdraw.h" + +#undef time + +#define MouseMask (\ + ButtonPressMask|\ + ButtonReleaseMask|\ + PointerMotionMask|\ + Button1MotionMask|\ + Button2MotionMask|\ + Button3MotionMask) + +#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask + +void runxevent(XEvent*); + +void +usage(void) +{ + fprint(2, "usage: snarf [-a] [-o | text]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int apple; + int out; + + apple = 0; + out = 0; + + ARGBEGIN{ + case 'a': + apple = 1; + break; + case 'o': + out = 1; + break; + default: + usage(); + }ARGEND + + if(out && argc != 0) + usage(); + if(!out && argc != 1) + usage(); + + _x.fd = -1; + + memimageinit(); + _xattach("snarf", "20x20"); + + XSelectInput(_x.display, _x.drawable, Mask); + XFlush(_x.display); + + if(out){ + char *s; + if(apple) + s = _applegetsnarf(); + else + s = _xgetsnarf(); + write(1, s, strlen(s)); + write(1, "\n", 1); + exits(0); + }else{ + _xputsnarf(argv[0]); + for(;;){ + XEvent event; + XNextEvent(_x.display, &event); + runxevent(&event); + } + } +} + +/* + * Handle an incoming X event. + */ +void +runxevent(XEvent *xev) +{ + switch(xev->type){ + case Expose: + _xexpose(xev); + break; + + case DestroyNotify: + if(_xdestroy(xev)) + exits(0); + break; + + case SelectionRequest: + _xselect(xev); + break; + } +} + diff --git a/src/cmd/devdraw/x11-itrans.c b/src/cmd/devdraw/x11-itrans.c index 81c5351c..fdd2bf8d 100644 --- a/src/cmd/devdraw/x11-itrans.c +++ b/src/cmd/devdraw/x11-itrans.c @@ -382,13 +382,61 @@ struct { #endif } clip; -char* -_xgetsnarf(void) +static uchar* +_xgetsnarffrom(XWindow w, Atom clipboard, Atom target, int timeout0, int timeout) { - uchar *data, *xdata; - Atom clipboard, type, prop; + Atom prop, type; ulong len, lastlen, dummy; int fmt, i; + uchar *data, *xdata; + + /* + * We should be waiting for SelectionNotify here, but it might never + * come, and we have no way to time out. Instead, we will clear + * local property #1, request our buddy to fill it in for us, and poll + * until he's done or we get tired of waiting. + */ + prop = 1; + XChangeProperty(_x.display, _x.drawable, prop, target, 8, PropModeReplace, (uchar*)"", 0); + XConvertSelection(_x.display, clipboard, target, prop, _x.drawable, CurrentTime); + XFlush(_x.display); + lastlen = 0; + timeout0 = (timeout0 + 9)/10; + timeout = (timeout + 9)/10; + for(i=0; i 0) + break; + lastlen = len; + XFree(xdata); + } + if(len == 0) + return nil; + + /* get the property */ + xdata = nil; + XGetWindowProperty(_x.display, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, + AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); + if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){ + if(xdata) + XFree(xdata); + return nil; + } + if(xdata){ + data = (uchar*)strdup((char*)xdata); + XFree(xdata); + return data; + } + return nil; +} + +char* +_xgetsnarf(void) +{ + uchar *data; + Atom clipboard; XWindow w; qlock(&clip.lk); @@ -427,47 +475,11 @@ _xgetsnarf(void) goto out; } - /* - * We should be waiting for SelectionNotify here, but it might never - * come, and we have no way to time out. Instead, we will clear - * local property #1, request our buddy to fill it in for us, and poll - * until he's done or we get tired of waiting. - * - * We should try to go for _x.utf8string instead of XA_STRING, - * but that would add to the polling. - */ - prop = 1; - XChangeProperty(_x.display, _x.drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); - XConvertSelection(_x.display, clipboard, XA_STRING, prop, _x.drawable, CurrentTime); - XFlush(_x.display); - lastlen = 0; - for(i=0; i<10 || (lastlen!=0 && i<30); i++){ - usleep(100*1000); - XGetWindowProperty(_x.display, _x.drawable, prop, 0, 0, 0, AnyPropertyType, - &type, &fmt, &dummy, &len, &data); - if(lastlen == len && len > 0) - break; - lastlen = len; - } - if(i == 10){ - data = nil; - goto out; - } - /* get the property */ - data = nil; - XGetWindowProperty(_x.display, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, - AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); - if((type != XA_STRING && type != _x.utf8string) || len == 0){ - if(xdata) - XFree(xdata); - data = nil; - }else{ - if(xdata){ - data = (uchar*)strdup((char*)xdata); - XFree(xdata); - }else - data = nil; + if((data = _xgetsnarffrom(w, clipboard, _x.utf8string, 10, 100)) == nil) + if((data = _xgetsnarffrom(w, clipboard, XA_STRING, 10, 100)) == nil){ + /* nothing left to do */ } + out: qunlock(&clip.lk); return (char*)data; -- cgit v1.2.3