tmove snarfer to use X includes - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit bb3b0aeb9c29e8dc21d8e48390ae4ce410563e3c
 (DIR) parent 5db07ba9422804c9de1e8fbda5486722cb731e03
 (HTM) Author: rsc <devnull@localhost>
       Date:   Fri,  3 Mar 2006 01:42:25 +0000
       
       move snarfer to use X includes
       
       Diffstat:
         A src/cmd/snarfer/mkfile              |       9 +++++++++
         A src/cmd/snarfer/snarfer.c           |     310 +++++++++++++++++++++++++++++++
       
       2 files changed, 319 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/snarfer/mkfile b/src/cmd/snarfer/mkfile
       t@@ -0,0 +1,9 @@
       +<$PLAN9/src/mkhdr
       +
       +TARG=snarfer
       +OFILES=
       +HFILES=
       +
       +<|sh ../../libdraw/mkwsysrules.sh
       +<$PLAN9/src/mkmany
       +
 (DIR) diff --git a/src/cmd/snarfer/snarfer.c b/src/cmd/snarfer/snarfer.c
       t@@ -0,0 +1,310 @@
       +/*
       + * This program is only intended for OS X, but the
       + * ifdef __APPLE__ below lets us build it on all systems.
       + * On non-OS X systems, you can use it to hold the snarf
       + * buffer around after a program exits.
       + */
       +
       +#include <u.h>
       +#define Colormap        XColormap
       +#define Cursor                XCursor
       +#define Display                XDisplay
       +#define Drawable        XDrawable
       +#define Font                XFont
       +#define GC                XGC
       +#define Point                XPoint
       +#define Rectangle        XRectangle
       +#define Screen                XScreen
       +#define Visual                XVisual
       +#define Window                XWindow
       +#include <X11/Xlib.h>
       +#include <X11/Xatom.h>
       +#include <X11/Xutil.h>
       +#include <X11/keysym.h>
       +#include <X11/IntrinsicP.h>
       +#include <X11/StringDefs.h>
       +#undef Colormap
       +#undef Cursor
       +#undef Display
       +#undef Drawable
       +#undef Font
       +#undef GC
       +#undef Point
       +#undef Rectangle
       +#undef Screen
       +#undef Visual
       +#undef Window
       +#ifdef __APPLE__
       +#define APPLESNARF
       +#define Boolean AppleBoolean
       +#define Rect AppleRect
       +#define EventMask AppleEventMask
       +#define Point ApplePoint
       +#define Cursor AppleCursor
       +#include <Carbon/Carbon.h>
       +AUTOFRAMEWORK(Carbon)
       +#undef Boolean
       +#undef Rect
       +#undef EventMask
       +#undef Point
       +#undef Cursor
       +#endif
       +#include <libc.h>
       +#undef time
       +AUTOLIB(draw)        /* to cause link of X11 */
       +
       +enum {
       +        SnarfSize = 65536,
       +};
       +char snarf[3*SnarfSize+1];
       +Rune rsnarf[SnarfSize+1];
       +XDisplay *xdisplay;
       +XWindow drawable;
       +Atom xclipboard;
       +Atom xutf8string;
       +Atom xtargets;
       +Atom xtext;
       +Atom xcompoundtext;
       +
       +void xselectionrequest(XEvent*);
       +char *xgetsnarf(void);
       +void appleputsnarf(void);
       +void xputsnarf(void);
       +
       +int verbose;
       +
       +#ifdef __APPLE__
       +PasteboardRef appleclip;
       +#endif
       +
       +void
       +usage(void)
       +{
       +        fprint(2, "usage: snarfer [-v]\n");
       +        exits("usage");
       +}
       +
       +void
       +main(int argc, char **argv)
       +{
       +        XEvent xevent;
       +        
       +        ARGBEGIN{
       +        default:
       +                usage();
       +        case 'v':
       +                verbose = 1;
       +                break;
       +        }ARGEND
       +
       +        if((xdisplay = XOpenDisplay(nil)) == nil)
       +                sysfatal("XOpenDisplay: %r");
       +        drawable = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay), 
       +                0, 0, 1, 1, 0, 0, 
       +                InputOutput, DefaultVisual(xdisplay, DefaultScreen(xdisplay)), 
       +                0, 0);
       +        if(drawable == None)
       +                sysfatal("XCreateWindow: %r");
       +        XFlush(xdisplay);
       +        
       +        xclipboard = XInternAtom(xdisplay, "CLIPBOARD", False);
       +        xutf8string = XInternAtom(xdisplay, "UTF8_STRING", False);
       +        xtargets = XInternAtom(xdisplay, "TARGETS", False);
       +        xtext = XInternAtom(xdisplay, "TEXT", False);
       +        xcompoundtext = XInternAtom(xdisplay, "COMPOUND_TEXT", False);
       +
       +#ifdef __APPLE__
       +        if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr)
       +                sysfatal("pasteboard create failed");
       +#endif
       +
       +        xgetsnarf();
       +        appleputsnarf();
       +        xputsnarf();
       +        
       +        for(;;){
       +                XNextEvent(xdisplay, &xevent);
       +                switch(xevent.type){
       +                case DestroyNotify:
       +                        exits(0);
       +                case SelectionClear:
       +                        xgetsnarf();
       +                        appleputsnarf();
       +                        xputsnarf();
       +                        if(verbose)
       +                                print("snarf{%s}\n", snarf);
       +                        break;
       +                case SelectionRequest:
       +                        xselectionrequest(&xevent);
       +                        break;
       +                }
       +        }
       +}
       +
       +void
       +xselectionrequest(XEvent *e)
       +{
       +        char *name;
       +        Atom a[4];
       +        XEvent r;
       +        XSelectionRequestEvent *xe;
       +        XDisplay *xd;
       +        
       +        xd = xdisplay;
       +        
       +        memset(&r, 0, sizeof r);
       +        xe = (XSelectionRequestEvent*)e;
       +if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n",
       +        xe->target, xe->requestor, xe->property, xe->selection);
       +        r.xselection.property = xe->property;
       +        if(xe->target == xtargets){
       +                a[0] = XA_STRING;
       +                a[1] = xutf8string;
       +                a[2] = xtext;
       +                a[3] = xcompoundtext;
       +
       +                XChangeProperty(xd, xe->requestor, xe->property, xe->target,
       +                        8, PropModeReplace, (uchar*)a, sizeof a);
       +        }else if(xe->target == XA_STRING || xe->target == xutf8string || xe->target == xtext || xe->target == xcompoundtext){
       +                /* if the target is STRING we're supposed to reply with Latin1 XXX */
       +                XChangeProperty(xd, xe->requestor, xe->property, xe->target,
       +                        8, PropModeReplace, (uchar*)snarf, strlen(snarf));
       +        }else{
       +                name = XGetAtomName(xd, xe->target);
       +                if(strcmp(name, "TIMESTAMP") != 0)
       +                        fprint(2, "%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
       +                r.xselection.property = None;
       +        }
       +
       +        r.xselection.display = xe->display;
       +        /* r.xselection.property filled above */
       +        r.xselection.target = xe->target;
       +        r.xselection.type = SelectionNotify;
       +        r.xselection.requestor = xe->requestor;
       +        r.xselection.time = xe->time;
       +        r.xselection.send_event = True;
       +        r.xselection.selection = xe->selection;
       +        XSendEvent(xd, xe->requestor, False, 0, &r);
       +        XFlush(xd);
       +}
       +
       +char*
       +xgetsnarf(void)
       +{
       +        uchar *data, *xdata;
       +        Atom clipboard, type, prop;
       +        ulong len, lastlen, dummy;
       +        int fmt, i;
       +        XWindow w;
       +        XDisplay *xd;
       +        
       +        xd = xdisplay;
       +
       +        /*
       +         * Is there a primary selection (highlighted text in an xterm)?
       +         */
       +        clipboard = XA_PRIMARY;
       +        w = XGetSelectionOwner(xd, XA_PRIMARY);
       +        if(w == drawable)
       +                return snarf;
       +
       +        /*
       +         * If not, is there a clipboard selection?
       +         */
       +        if(w == None && xclipboard != None){
       +                clipboard = xclipboard;
       +                w = XGetSelectionOwner(xd, xclipboard);
       +                if(w == drawable)
       +                        return snarf;
       +        }
       +
       +        /*
       +         * If not, give up.
       +         */
       +        if(w == None)
       +                return nil;
       +                
       +        /*
       +         * 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(xd, drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
       +        XConvertSelection(xd, clipboard, XA_STRING, prop, drawable, CurrentTime);
       +        XFlush(xd);
       +        lastlen = 0;
       +        for(i=0; i<10 || (lastlen!=0 && i<30); i++){
       +                sleep(100);
       +                XGetWindowProperty(xd, drawable, prop, 0, 0, 0, AnyPropertyType,
       +                        &type, &fmt, &dummy, &len, &data);
       +                if(lastlen == len && len > 0)
       +                        break;
       +                lastlen = len;
       +        }
       +        if(i == 10)
       +                return nil;
       +        /* get the property */
       +        data = nil;
       +        XGetWindowProperty(xd, drawable, prop, 0, SnarfSize/sizeof(ulong), 0, 
       +                AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
       +        if(xdata == nil || (type != XA_STRING && type != xutf8string) || len == 0){
       +                if(xdata)
       +                        XFree(xdata);
       +                return nil;
       +        }
       +        if(strlen((char*)xdata) >= SnarfSize){
       +                XFree(xdata);
       +                return nil;
       +        }
       +        strcpy(snarf, (char*)xdata);
       +        return snarf;
       +}
       +
       +void
       +xputsnarf(void)
       +{
       +        XSetSelectionOwner(xdisplay, XA_PRIMARY, drawable, CurrentTime);
       +        if(xclipboard != None)
       +                XSetSelectionOwner(xdisplay, xclipboard, drawable, CurrentTime);
       +        XFlush(xdisplay);
       +}
       +
       +void
       +appleputsnarf(void)
       +{
       +#ifdef __APPLE__
       +        CFDataRef cfdata;
       +        PasteboardSyncFlags flags;
       +
       +        runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
       +        if(PasteboardClear(appleclip) != noErr){
       +                fprint(2, "apple pasteboard clear failed\n");
       +                return;
       +        }
       +        flags = PasteboardSynchronize(appleclip);
       +        if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
       +                fprint(2, "apple pasteboard cannot assert ownership\n");
       +                return;
       +        }
       +        cfdata = CFDataCreate(kCFAllocatorDefault, 
       +                (uchar*)rsnarf, runestrlen(rsnarf)*2);
       +        if(cfdata == nil){
       +                fprint(2, "apple pasteboard cfdatacreate failed\n");
       +                return;
       +        }
       +        if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
       +                CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
       +                fprint(2, "apple pasteboard putitem failed\n");
       +                CFRelease(cfdata);
       +                return;
       +        }
       +        CFRelease(cfdata);
       +#endif
       +}
       +
       +