From 8f86fa5f8c65066c31acc930a3bd094f7381a2e4 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 29 Nov 2013 18:41:32 +0000 Subject: [PATCH] xduplic-copier: as found on chiark --- cprogs/xduplic-copier.c | 281 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 cprogs/xduplic-copier.c diff --git a/cprogs/xduplic-copier.c b/cprogs/xduplic-copier.c new file mode 100644 index 0000000..ff0830d --- /dev/null +++ b/cprogs/xduplic-copier.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2002 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static Display *display; +static int selecting, l1_x, l1_y; +static char stringbuf[20]; +static unsigned long c_black, c_white, c_red, c_yellow; +static Window w, root; +static Cursor cursor; +static GC gc; +static Colormap cmap; + +struct wnode { + struct wnode *next; + Window w; +} *headwn; + +static unsigned long getcolour(const char *name, int def) { + Status st; + XColor screen_def, exact_def; + st= XAllocNamedColor(display,cmap,name,&screen_def,&exact_def); + fprintf(stdout,"name %s pixel %lu\n",name,screen_def.pixel); + return st ? screen_def.pixel : def; +} + +static void beep(void) { XBell(display,100); } + +/* + * While selecting: + * Left Right + * application select deselect + * root start typing deselect all + * xduplic start typing quit + * + * While typing: + * Left Right + * xduplic start selecting quit + * + * Colours: + * + * While typing: yellow on black + * While selecting: white on black + * Idle (typing into nowhere): red on black + */ + +static void redisplay(void) { + XClearWindow(display,w); + XDrawString(display,w,gc, l1_x,l1_y, stringbuf,strlen(stringbuf)); +} + +static void restatus(void) { + XGCValues v; + int count; + struct wnode *own; + + v.foreground= (selecting ? c_white : + headwn ? c_yellow : + c_red); + + XChangeGC(display,gc, + GCForeground, + &v); + XClearWindow(display,w); + + for (count=0, own=headwn; own; own=own->next) count++; + snprintf(stringbuf,sizeof(stringbuf), + "%c %d", + selecting ? 'S' : + headwn ? 'T' : 'i', + count); + redisplay(); +} + +static void stopselecting(void) { + XUngrabPointer(display,CurrentTime); + selecting= 0; + restatus(); +} + +static void startselecting(void) { + Status st; + st= XGrabPointer(display,root,True, + ButtonPressMask,GrabModeAsync, + GrabModeAsync,None,cursor,CurrentTime); + if (st != Success) beep(); + else selecting= 1; + restatus(); +} + +static void buttonpress(XButtonEvent *e) { + struct wnode *own, **ownp, *ownn; + int rightbutton; + Window sw; + + switch (e->button) { + case Button1: rightbutton=0; break; + case Button3: rightbutton=1; break; + default: return; + } + + fprintf(stdout,"button right=%d in=%lx sub=%lx (w=%lx root=%lx)\n", + rightbutton, (unsigned long)e->window, (unsigned long)e->subwindow, + (unsigned long)w, (unsigned long)e->root); + + if (e->window == w) { + if (rightbutton) _exit(0); + if (selecting) { + stopselecting(); + /* move pointer to where it already is, just in case wm is confused */ + XWarpPointer(display,None,root, 0,0,0,0, e->x_root,e->y_root); + } else { + startselecting(); + } + return; + } + + if (!selecting) return; + + if (e->window != e->root) return; + + sw= XmuClientWindow(display, e->subwindow); + if (!sw) { + if (!rightbutton) { + stopselecting(); + } else { + if (!headwn) { beep(); return; } + for (own=headwn; own; own=ownn) { + ownn= own->next; + free(own); + } + headwn= 0; + restatus(); + } + return; + } + + if (sw == w) { beep(); return; } + + for (ownp=&headwn; + (own=(*ownp)) && own->w != sw; + ownp= &(*ownp)->next); + + if (!rightbutton) { + + if (own) { beep(); return; } + own= malloc(sizeof(*own)); if (!own) { perror("malloc"); exit(-1); } + own->w= sw; + own->next= headwn; + headwn= own; + + } else { + + if (!own) { beep(); return; } + *ownp= own->next; + free(own); + + } + + restatus(); +} + +static void keypress(XKeyEvent *e) { + Status st; + struct wnode *own; + unsigned long mask; + + if (selecting) { + fprintf(stdout,"key type %d serial %lu (send %d) " + "window %lx root %lx sub %lx time %lx @%dx%d (%dx%dabs) " + "state %x keycode %u same %d\n", + e->type, e->serial, (int)e->send_event, + (unsigned long)e->window, + (unsigned long)e->root, + (unsigned long)e->subwindow, + (unsigned long)e->time, + e->x,e->y, e->x_root,e->y_root, + e->state, e->keycode, (int)e->same_screen); + if (XKeycodeToKeysym(display, e->keycode, 0) == XK_q) _exit(1); + beep(); return; + } + for (own=headwn; own; own=own->next) { + mask= (e->type == KeyPress ? KeyPressMask : + e->type == KeyRelease ? KeyReleaseMask : + KeyPressMask|KeyReleaseMask); + e->window= own->w; + e->subwindow= None; + e->send_event= True; + st= XSendEvent(display,own->w,True,mask,(XEvent*)e); + if (st != Success) { + fprintf(stdout,"sendevent to %lx %d mask %lx\n", + (unsigned long)own->w, st, mask); + } + } +} + +static void expose(XExposeEvent *e) { + if (e->count) return; + redisplay(); +} + +int main(int argc, const char **argv) { + XEvent e; + XGCValues gcv; + XSetWindowAttributes wv; + int screen, direction, ascent, descent, l1_width, l1_height; + XCharStruct overall; + Font font; + + display= XOpenDisplay(0); + screen= DefaultScreen(display); + cmap= DefaultColormap(display,screen); + root= DefaultRootWindow(display); + + c_black= getcolour("black", 0); + c_white= getcolour("white", 1); + c_yellow= getcolour("yellow", c_white); + c_red= getcolour("red", c_white); + + cursor= XCreateFontCursor(display,XC_crosshair); + + wv.event_mask= KeyPressMask|KeyReleaseMask|ButtonPressMask|ExposureMask; + w= XCreateWindow(display, root, + 0,0, 50,21, 0,DefaultDepth(display,screen), + InputOutput, DefaultVisual(display,screen), + CWEventMask, &wv); + + font= XLoadFont(display,"fixed"); + + gcv.background= c_black; + gcv.font= font; + gc= XCreateGC(display,w,GCBackground|GCFont,&gcv); + + XQueryTextExtents(display,font, "SIT 0689", 8, + &direction,&ascent,&descent,&overall); + l1_width= overall.lbearing + overall.rbearing; + l1_x= overall.lbearing; + l1_y= ascent; + l1_height= descent+ascent; + + XResizeWindow(display,w, l1_width,l1_height); + XSetWindowBackground(display,w,c_black); + + XMapWindow(display,w); + restatus(); + + for (;;) { + XNextEvent(display,&e); + fprintf(stdout,"selecting = %d; event type = %lu\n", + selecting, (unsigned long)e.type); + switch (e.type) { + case Expose: expose(&e.xexpose); break; + case ButtonPress: buttonpress(&e.xbutton); break; + case KeyPress: case KeyRelease: keypress(&e.xkey); break; + } + } +} -- 2.30.2