URI: 
       ttry for utf8 string first in getsnarf; new test program snarf - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 0335ceaeb695ab5e92d0d0cd1f554373056c8696
   DIR parent 703c2d41ac5462f5d82e781b50d051a4a579416c
  HTML Author: rsc <devnull@localhost>
       Date:   Thu,  3 May 2007 19:13:56 +0000
       
       ttry for utf8 string first in getsnarf; new test program snarf
       
       Diffstat:
         M src/cmd/devdraw/mkfile              |       2 ++
         A src/cmd/devdraw/snarf.c             |     110 +++++++++++++++++++++++++++++++
         M src/cmd/devdraw/x11-itrans.c        |     100 +++++++++++++++++--------------
       
       3 files changed, 168 insertions(+), 44 deletions(-)
       ---
   DIR diff --git a/src/cmd/devdraw/mkfile b/src/cmd/devdraw/mkfile
       t@@ -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
   DIR diff --git a/src/cmd/devdraw/snarf.c b/src/cmd/devdraw/snarf.c
       t@@ -0,0 +1,110 @@
       +#include <u.h>
       +#include <sys/select.h>
       +#include <errno.h>
       +#include "x11-inc.h"
       +#include <libc.h>
       +#include <draw.h>
       +#include <memdraw.h>
       +#include <memlayer.h>
       +#include <keyboard.h>
       +#include <mouse.h>
       +#include <cursor.h>
       +#include <drawfcall.h>
       +#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;
       +        }
       +}
       +
   DIR diff --git a/src/cmd/devdraw/x11-itrans.c b/src/cmd/devdraw/x11-itrans.c
       t@@ -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<timeout0 || (lastlen!=0 && i<timeout); i++){
       +                usleep(10*1000);
       +                XGetWindowProperty(_x.display, _x.drawable, prop, 0, 0, 0, AnyPropertyType,
       +                        &type, &fmt, &dummy, &len, &xdata);
       +                if(lastlen == len && len > 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);
       t@@ -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;