Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!udel!rochester!ferguson From: ferguson@cs.rochester.edu (George Ferguson) Newsgroups: alt.sources Subject: xse - An interface to XSendEvent() part01/03 REPOST Message-ID: <1990Aug16.193522.11240@cs.rochester.edu> Date: 16 Aug 90 19:35:22 GMT Reply-To: ferguson@cs.rochester.edu (George Ferguson) Distribution: alt Organization: U of Rochester, CS Dept, Rochester, NY Lines: 816 I've had several requests to attempt a repost, so here goes. Apologies to those who are (understandably) frustrated by my and my poster's screwups. George #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Imakefile' <<'END_OF_FILE' X/**/# X/**/# Imakefile for xse - An interface to XSendEvent() X/**/# X/**/# George Ferguson, ferguson@cs.rochester.edu, 1 Jun 1990. X/**/# X/**/# $Id: Imakefile,v 1.3 90/08/15 11:32:06 ferguson Exp $ X/**/# X X#ifdef BandAidCompiler X#include BandAidCompiler X#endif X XDEPLIBS = XawClientDepLibs XLOCAL_LIBRARIES = XawClientLibs XCDEBUGFLAGS = -g X XAD2C = ./ad2c X XSRCS = xse.c parse.c translate.c XOBJS = xse.o parse.o translate.o XINCS = app-resources.h parse.h translate.h X XComplexProgramTarget(xse) X X/**/# X/**/# C code for fallback resources X/**/# XXse.ad.h: Xse.ad X $(AD2C) Xse.ad >Xse.ad.h X X/**/# X/**/# Misc X/**/# X Xci: X ci -u -q -m' ' -t/dev/null Imakefile $(SRCS) $(INCS) xse.man X Xclean:: X rm Xse.ad.h END_OF_FILE if test 694 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(126 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' XMANIFEST XREADME XImakefile XMakefile XXse.ad Xad2c Xad2c.sed Xapp-resources.h Xparse.c Xparse.h Xtranslate.c Xtranslate.h Xxse.c Xxse.man END_OF_FILE if test 126 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1689 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X XSE - An interface to XSendEvent() X X George Ferguson, ferguson@cs.rochester.edu X XOVERVIEW: X XXse provides an interface to XSendEvent(); sort of an inverse of xev(1). XIt provides two interfaces depending on how it is invoked. If extra Xcommand-line arguments are given, then these are parsed into an event Xsequence and sent to the proper window (either the default or the one Xgiven by the "-window" argument). If no event sequence is given, then Xxse creates a tool as specified by the "widgets" resource of its Xapplication-defaults file. Presumably this tool will create Command buttons Xor menus which will use the xse-send() and xse-quit() actions. X XIncluded in this distribution is the program "ad2c" which converts an Xapplication-defaults file to C declarations for inclusion as fallback Xresources. Also, the code used to specify and create widgets from a Xresource entry is very modular (see translate.c and initWidgets() in Xxse.c). X X XINSTALLATION: X X 1. Edit the Imakefile as necessary to reflect changes for your X site. In particular, you may want to set BINDIR and MANDIR to X change the install targets. You may have to edit the filename X used in "ad2c" (the name of the sed script). X X 2. Execute X % xmkmf X to make the Makefile. X X 3. Execute X % make depend X to add the dependencies to the Makefile. IMPORTANT: Ignore the X warning message from makedepend about missing Xse.ad.h; it will X be created automatically. X X 4. Execute X % make X to make the program or X % make install install.man X to make and install it. Making xse required the program ad2c X to translate an application-defaults file into C declarations. X Ad2c should be included with this distribution. END_OF_FILE if test 1689 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'Xse.ad' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Xse.ad'\" else echo shar: Extracting \"'Xse.ad'\" \(727 characters\) sed "s/^X//" >'Xse.ad' <<'END_OF_FILE' X! X! Xse.ad - Resources for xse: An interface to XSendEvent() X! X! George Ferguson, fergsuon@cs.rochester.edu, 1 Jun 1990. X! X! $Id: Xse.ad,v 1.4 90/08/15 11:32:13 ferguson Exp $ X! X! This has must be the first line in the "official" app-defaults file. XXse.revision: $Revision: 1.4 $ X X! Non-widget stuff X XXse.window: InputFocus X X X! Widget stuff X XXse.widgets: \ X Form form toplevel \n\ X Command button1 form \n\ X Command button2 form \n X XXse*button1.label: send a to default window XXse*button1.translations:#override\n\ X , : xse-send(a)\n X XXse*button2.label: send a to ClickWindow XXse*button2.fromVert: button1 XXse*button2.translations:#override\n\ X , : xse-send(ClickWindow,a)\n END_OF_FILE if test 727 -ne `wc -c <'Xse.ad'`; then echo shar: \"'Xse.ad'\" unpacked with wrong size! fi # end of 'Xse.ad' fi if test -f 'ad2c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ad2c'\" else echo shar: Extracting \"'ad2c'\" \(86 characters\) sed "s/^X//" >'ad2c' <<'END_OF_FILE' X#!/bin/csh X# X# Convert app-defaults file to C strings decls. X# X Xsed -n -f ad2c.sed $* END_OF_FILE if test 86 -ne `wc -c <'ad2c'`; then echo shar: \"'ad2c'\" unpacked with wrong size! fi chmod +x 'ad2c' # end of 'ad2c' fi if test -f 'ad2c.sed' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ad2c.sed'\" else echo shar: Extracting \"'ad2c.sed'\" \(470 characters\) sed "s/^X//" >'ad2c.sed' <<'END_OF_FILE' X# X# Convert app-defaults file to C strings decls. X# X# Invoke by: sed -n -f ad2c.sed X# X: read X# remove comments X/^!/d X# remove blanks X/^$/d X# escape quotes Xs/"/\\"/g X# escape backslash Xs/\\/\\\\/g X# except the line continuation ones Xs/\\$//g X# add leading quote Xs/^/"/ X# X: test X/\\$/b slash Xs/$/",/ Xp Xn Xb read X# X: slash Xp Xn X# just like "read" only doesn't add leading quote X/^!/d X/^$/d Xs/"/\\"/g Xs/\\\\/\\/g Xs/\\n/\\\\n/g Xs/\\t/\\\\t/g Xs/\\f/\\\\f/g Xs/\\b/\\\\b/g Xb test END_OF_FILE if test 470 -ne `wc -c <'ad2c.sed'`; then echo shar: \"'ad2c.sed'\" unpacked with wrong size! fi # end of 'ad2c.sed' fi if test -f 'app-resources.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'app-resources.h'\" else echo shar: Extracting \"'app-resources.h'\" \(306 characters\) sed "s/^X//" >'app-resources.h' <<'END_OF_FILE' X/* X * app-resources.h : External app-defaults defs. X * X * George Ferguson, ferguson@cs.rochester.edu, 1 Jun 1990. X * X * $Id: app-resources.h,v 1.1 90/08/15 10:22:35 ferguson Exp $ X * X */ Xtypedef struct { X String window; X String widgets; X String revision; X} AppResources; Xextern AppResources appResources; END_OF_FILE if test 306 -ne `wc -c <'app-resources.h'`; then echo shar: \"'app-resources.h'\" unpacked with wrong size! fi # end of 'app-resources.h' fi if test -f 'parse.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'parse.h'\" else echo shar: Extracting \"'parse.h'\" \(290 characters\) sed "s/^X//" >'parse.h' <<'END_OF_FILE' X/* X * parse.h - George Ferguson, ferguson@cs.rochester.edu, 1 Jun 1990. X * X * $Id: parse.h,v 1.1 90/08/15 10:22:42 ferguson Exp $ X */ X Xtypedef struct eventListStruct { X XEvent event; X long count; X struct eventListStruct *next; X} EventListElem,*EventListPtr; X Xextern char *parseEventList(); END_OF_FILE if test 290 -ne `wc -c <'parse.h'`; then echo shar: \"'parse.h'\" unpacked with wrong size! fi # end of 'parse.h' fi if test -f 'translate.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'translate.c'\" else echo shar: Extracting \"'translate.c'\" \(2196 characters\) sed "s/^X//" >'translate.c' <<'END_OF_FILE' X/* X * translate.c : Map class names to classes. This code is X * totally self-contained. A smaller executable X * might result from only including the classes X * an application needs. X * X * George Ferguson, ferguson@cs.rochester.edu, 15 Jul 1990. X * X * $Id: translate.c,v 1.1 90/08/15 10:22:44 ferguson Exp $ X */ X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xstatic struct tableRec { X char *name; X WidgetClass *class; X Boolean isShell; X} table[] = { X { "Command", &commandWidgetClass, False }, X { "Grip", &gripWidgetClass, False }, X { "Label", &labelWidgetClass, False }, X { "List", &listWidgetClass, False }, X { "Scrollbar", &scrollbarWidgetClass, False }, X { "Simple", &simpleWidgetClass, False }, X { "StripChart", &stripChartWidgetClass, False }, X { "Toggle", &toggleWidgetClass, False }, X { "SimpleMenu", &simpleMenuWidgetClass, True }, X { "SmeBSB", &smeBSBObjectClass, False }, X { "SmeLine", &smeLineObjectClass, False }, X { "MenuButton", &menuButtonWidgetClass, False }, X { "AsciiText", &asciiTextWidgetClass, False }, X { "Box", &boxWidgetClass, False }, X { "Dialog", &dialogWidgetClass, False }, X { "Form", &formWidgetClass, False }, X { "Paned", &panedWidgetClass, False }, X { "Viewport", &viewportWidgetClass, False }, X { "TransientShell", &transientShellWidgetClass, True }, X { "ApplicationShell", &applicationShellWidgetClass, True }, X}; X XWidgetClass XclassNameToWidgetClass(name,isShell) Xchar *name; XBoolean *isShell; X{ X int i; X X for (i=0; i < XtNumber(table); i++) X if (strcmp(name,table[i].name) == 0) { X *isShell = table[i].isShell; X return(*(table[i].class)); X } X return((WidgetClass)NULL); X} END_OF_FILE if test 2196 -ne `wc -c <'translate.c'`; then echo shar: \"'translate.c'\" unpacked with wrong size! fi # end of 'translate.c' fi if test -f 'translate.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'translate.h'\" else echo shar: Extracting \"'translate.h'\" \(45 characters\) sed "s/^X//" >'translate.h' <<'END_OF_FILE' Xextern WidgetClass classNameToWidgetClass(); END_OF_FILE if test 45 -ne `wc -c <'translate.h'`; then echo shar: \"'translate.h'\" unpacked with wrong size! fi # end of 'translate.h' fi if test -f 'xse.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xse.c'\" else echo shar: Extracting \"'xse.c'\" \(9393 characters\) sed "s/^X//" >'xse.c' <<'END_OF_FILE' X/* X * xse - an interface to XSendEvent() X * X * George Ferguson, ferguson@cs.rochester.edu, 1 Jun 1990. X * X * $Id: xse.c,v 1.4 90/08/15 11:32:30 ferguson Exp $ X * X */ Xstatic char *rcsid = "$Id: xse.c,v 1.4 90/08/15 11:32:30 ferguson Exp $"; X#include X#include X#include X#include X#include X#include X#include X#include X#include "app-resources.h" X#include "translate.h" X#include "parse.h" X X/* - - - - - - - - */ X/* X * Functions defined in this file X */ Xstatic void initGraphics(),initWidgets(); Xstatic void quit(),send(); Xstatic void parseAndSendEvents(), fail(); Xstatic Window windowFromString(), Window_With_Name(), Select_Window(); X X/* X * Action binding table X */ Xstatic XtActionsRec cmdActionsTable[] = { X { "xse-quit", quit }, X { "xse-send", send }, X}; X X/* X * Global graphics data, needed in parse.c X */ XDisplay *display; XWindow root; X X/* X * Global widget data X */ Xstatic XtAppContext app_con; Xstatic Widget toplevel; X X/* X * The application resources struct X */ Xstatic AppResources appResources; X X/* X * Non-widget resources obtained from resource manager X */ Xstatic XtResource resources[] = { X { "widgets", "Widgets", XtRString, sizeof(String), X XtOffset(AppResources *,widgets), XtRImmediate, NULL }, X { "window", "Window", XtRString, sizeof(String), X XtOffset(AppResources *,window), XtRImmediate, "InputFocus" }, X { "revision", "Revision", XtRString, sizeof(String), X XtOffset(AppResources *,revision), XtRImmediate, "" }, X}; X X/* X * Non-widget resources set on command line. X */ Xstatic XrmOptionDescRec options[] = { X { "-window", "window", XrmoptionSepArg, "InputFocus"}, X}; X X/* X * Widget and non-widget resources if the application defaults X * file can't be found. X * [ Generated automatically from Xse.ad. ] X */ Xstatic String fallbackResources[] = { X#include "Xse.ad.h" X NULL X}; X X/* - - - - - - - - */ X/* X * main() : Initialize the graphics, then if args remain send them directly X * (ie. we are in command mode) otherwise initialize the widgets X * (ie. we are in widget mode) and call XtAppMainLoop(). X */ Xmain(argc, argv) Xint argc; Xchar **argv; X{ X Window win; X X initGraphics(&argc,argv); X argv += 1; X argc -= 1; X if (argc > 0) { X win = windowFromString(appResources.window); X while (argc--) X parseAndSendEvents(win,*argv++); X XtDestroyApplicationContext(app_con); X exit(0); X } X initWidgets(); X XtRealizeWidget(toplevel); X XtAppMainLoop(app_con); X} X X/* X * initGraphics() : Initialize the application context and set global X * graphics variables. X */ Xstatic void XinitGraphics(argcp,argv) Xint *argcp; Xchar **argv; X{ X toplevel = XtAppInitialize(&app_con, "Xse", X options, XtNumber(options), X argcp,argv,fallbackResources,NULL,ZERO); X XtGetApplicationResources(toplevel,(XtPointer)&appResources, X resources,XtNumber(resources),NULL,ZERO); X display = XtDisplay(toplevel); X root = RootWindowOfScreen(XtScreen(toplevel)); X XtAppAddActions(app_con,cmdActionsTable,XtNumber(cmdActionsTable)); X} X X/* X * initWidgets() : Parse the widgets resource and create whatever widgets X * specified in it as children of toplevel (or sub-children, X * etc.). X */ Xstatic void XinitWidgets() X{ X char name[32],class[32],parent[32]; X char *s; X int i; X Boolean isShell; X WidgetClass wc; X Widget w; X X if ((s=appResources.widgets) == NULL) X fail("no widgets specified!\n",""); X while (*s) { X while (isspace(*s)) X s += 1; X if (!*s) X break; X i = 0; X while (*s && !isspace(*s)) X class[i++] = *s++; X class[i] = '\0'; X while (isspace(*s)) X s += 1; X i = 0; X while (*s && !isspace(*s)) X name[i++] = *s++; X name[i] = '\0'; X while (isspace(*s)) X s += 1; X i = 0; X while (*s && !isspace(*s)) X parent[i++] = *s++; X parent[i] = '\0'; X isShell = False; X if ((wc=classNameToWidgetClass(class,&isShell)) == NULL) X fail("can't convert string \"%s\" to widgetClass\n",class); X if (strcmp(parent,"toplevel") == 0) X w = toplevel; X else if ((w=XtNameToWidget(toplevel,parent)) == NULL) X fail("can't convert string \"%s\" to widget\n",parent); X if (isShell) X w = XtCreatePopupShell(name,wc,w,NULL,ZERO); X else X w = XtCreateManagedWidget(name,wc,w,NULL,ZERO); X } X} X X/* - - - - - - - - */ X/* X * windowFromString() : Convert a string to a Window, handling our special X * cases of PointerWindow, InputFocus, or ClickWindow. X */ Xstatic Window XwindowFromString(str) Xchar *str; X{ X Window w; X X if (strcmp(str,"PointerWindow") == 0) X return(PointerWindow); X else if (strcmp(str,"InputFocus") == 0) X return(InputFocus); X else if (strcmp(str,"ClickWindow") == 0) X return(Select_Window(display)); X else if ((w=Window_With_Name(display,root,str)) != NULL) X return(w); X else X return((Window)strtol(str,NULL,0)); X} X X/* - - - - - - - - */ X/* Action procedures */ X X/* X * quit() : Quit the tool. X */ Xstatic void Xquit(w,event,params,num_params) XWidget w; XXEvent *event; XString *params; XCardinal *num_params; X{ X XtDestroyApplicationContext(app_con); X exit(0); X} X X/* X * send() : With one argument, send the event sequence given by the first X * argument to the default window. With two arguments, the first X * is the window to send the event sequence given by the second X * to. X */ Xstatic void Xsend(w,event,params,num_params) XWidget w; XXEvent *event; XString *params; XCardinal *num_params; X{ X char *estr,*wstr; X X if (*num_params == ONE) { X wstr = appResources.window; X estr = params[0]; X } else if (*num_params == TWO) { X wstr = params[0]; X estr = params[1]; X } else { X fprintf(stderr,"xse: too many arguments to xse-send()\n"); X return; X } X parseAndSendEvents(windowFromString(wstr),estr); X} X X/* X * parseAndSendEvents() : Calls parseEventList() then dispatches the list X * of returned events. X */ Xstatic void XparseAndSendEvents(window,str) XWindow window; Xchar *str; X{ X char *s; X EventListPtr list = NULL; X X s = parseEventList(str,&list); X if (*s != '\0') { X fprintf("xse: garbage at end of event spec: \"%s\"\n",s); X return; X } X while (list != NULL) { X if (list->event.xany.type != -1) { X list->event.xany.display = display; X list->event.xany.window = window; X while (list->count-- != 0) X XSendEvent(display,window,True,0xfff,&(list->event)); X } X list = list->next; X } X freeEventList(&list); X} X X/* - - - - - - - - */ X/* X * fail() : Print a message and die. X */ Xstatic void Xfail(fmt,arg) Xchar *fmt,*arg; X{ X fprintf(stderr,fmt,arg); X XtDestroyApplicationContext(app_con); X exit(1); X} X X/* - - - - - - - - */ X/* - - - - - - - - */ X/* X * [These functions are from the file "dsimple.c" used with xwininfo.] X * X * Written by Mark Lillibridge. Last updated 7/1/87 X * X * Send bugs, etc. to chariot@athena.mit.edu. X * X * Window_With_Name: routine to locate a window with a given name on a display. X * If no window with the given name is found, 0 is returned. X * If more than one window has the given name, the first X * one found will be returned. Only top and its subwindows X * are looked at. Normally, top should be the RootWindow. X */ Xstatic Window XWindow_With_Name(dpy, top, name) X Display *dpy; X Window top; X char *name; X{ X Window *children, dummy; X unsigned int nchildren; X int i; X Window w=0; X char *window_name; X X if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name)) X return(top); X X if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren)) X return(0); X X for (i=0; i X Xstatic Window XSelect_Window(dpy) X Display *dpy; X{ X static Cursor cursor = NULL; X Window target_win = None, root = DefaultRootWindow(dpy); X XEvent event; X int status; X int buttons = 0; X X if (cursor == NULL) X cursor = XCreateFontCursor(dpy, XC_crosshair); X /* Grab the pointer using target cursor, letting it room all over */ X status = XGrabPointer(dpy, root, False, X ButtonPressMask|ButtonReleaseMask, GrabModeSync, X GrabModeAsync, root, cursor, CurrentTime); X if (status != GrabSuccess) { X fprintf(stderr,"xse: can't grab pointer"); X return(None); X } X /* Let the user select a window... */ X while ((target_win == None) || (buttons != 0)) { X /* allow one more event */ X XAllowEvents(dpy, SyncPointer, CurrentTime); X XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event); X switch (event.type) { X case ButtonPress: X if (target_win == None) { X target_win = event.xbutton.subwindow; /* window selected */ X if (target_win == None) target_win = root; X } X buttons++; X break; X case ButtonRelease: X if (buttons > 0) /* there may have been some down before we started */ X buttons--; X break; X } X } X XUngrabPointer(dpy, CurrentTime); /* Done with pointer */ X return(target_win); X} END_OF_FILE if test 9393 -ne `wc -c <'xse.c'`; then echo shar: \"'xse.c'\" unpacked with wrong size! fi # end of 'xse.c' fi echo shar: End of archive 1 \(of 3\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- George Ferguson ARPA: ferguson@cs.rochester.edu University of Rochester UUCP: {decvax,rutgers}!rochester!ferguson Rochester NY 14627 VOX: (716) 275-2527