tmove snarfer to use X includes - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit bb3b0aeb9c29e8dc21d8e48390ae4ce410563e3c
parent 5db07ba9422804c9de1e8fbda5486722cb731e03
Author: rsc 
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(-)
---
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
+
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 
+#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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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 
+AUTOFRAMEWORK(Carbon)
+#undef Boolean
+#undef Rect
+#undef EventMask
+#undef Point
+#undef Cursor
+#endif
+#include 
+#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
+}
+
+