move snarfer to use X includes
This commit is contained in:
parent
5db07ba942
commit
bb3b0aeb9c
2 changed files with 319 additions and 0 deletions
9
src/cmd/snarfer/mkfile
Normal file
9
src/cmd/snarfer/mkfile
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
TARG=snarfer
|
||||||
|
OFILES=
|
||||||
|
HFILES=
|
||||||
|
|
||||||
|
<|sh ../../libdraw/mkwsysrules.sh
|
||||||
|
<$PLAN9/src/mkmany
|
||||||
|
|
||||||
310
src/cmd/snarfer/snarfer.c
Normal file
310
src/cmd/snarfer/snarfer.c
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue